• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆 - 55  文章 - 15  trackbacks - 0
            <2012年3月>
            26272829123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567

            常用鏈接

            留言簿

            隨筆分類

            隨筆檔案

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

                 Thinking in C++ 第二卷第五章的內容,先從模板的特化說起。模板的內容太豐富了,學習是一回事,要掌握模板肯定要在工作中經常使用。

            模板特化

            我們知道,模板描述了一族類或者一族函數。實例化一個模板類,就是在這一族類中拿出特定的一種。特化就是萬中取一的過程。

            顯式特化
            自己提供代碼,而不是在實例化的時候特化。
            例如:
            template<class T, class Allocator = allocator<T> >
            class vector{};


            template<> class vector<bool, allocator<bool> > {..};
            template<>明確告訴編譯器這是一個模板的特化。
            在特化一個類模板的時候,一般要實現其中的所有成員函數。由于所提供的時一個單獨的類,客戶代碼常常希望能提供完整的接口實現。

            半特化(偏特化)
            沒有完全特化成特定的類型,特化的不完全體,還保留其他可能性。例:
            template<class Allocator>class vector<bool, Allocator>{};
            用戶可以提供一個自定義的allocator。
            選擇哪個類模板來進行實例化的規則遵循“特化程度最高”的原則(半有序)。例:

            template<class T, class U>
            class X
            {
             public:
               void f(){ cout << " Primary Template" << endl;}
            };

            template< class U>
            class X<int, U>
            {
             public:
               void f(){ cout << " T==int" << endl;}
            };

            template< class U>
            class X<int, U>
            {
             public:
               void f(){ cout << " T==int" << endl;}
            }; 
            template<class T>
            class X<T,T>
            {
             public:
               void f(){ cout << "T==U" << endl;}
            };

            int main()
            {
              C<floatint>().f();// Primary tempalte
              C<intfloat>().f();// T==int
              C<int*, float*>().f();// T* and U* used , T = int, U = float

              C<intint>().f();//Duplicate X<int,U>, X<T>
              return 0;
            }

            即,在特化或者偏特化的時候不要讓編譯器為難,盡量避免二義性的出現。
            ps:如果類參數符合偏特化,就調用偏特化, 如果符合幾個偏特化,出現二義性,編譯錯誤


            防止代碼膨脹

            一旦對某個類模板進行了實例化, 伴隨著所有在程序中調用的該模板的成員函數,類定義中用于對其進行詳盡描述的特化代碼也會產生。只有被調用的成員函數才產生代碼。例:

            class X
            {
             public
               void f(){}
            };

            class Y
            {
            public:
             void g(){}
            };

            template<class T> class Z
            {
            T t;
            public:
              void a(){ t.f();}
              void b(){ t.g();}
            };

            int main()
            {
             Z<X> zx;
             zx.a();//Doesn't create Z<X>::b()
             Z<Y> zy;
             zy.b();//Doesn't create Z<Y>::a()
             return 0;
            }

            但是雖然我們在代碼中只寫了一份,但是當你要將該類模板實例化為int型,void型和其他類型的時候,你會發現,編譯器在后臺為你復制粘貼了一系列相應的代碼,這使我們的代碼膨脹。解決方法是用void*進行完全特化,然后從void* 實現中派生出所有其他的指針類型。

            template<class T>
            class Stack
            {
              T* data;
             public
              void push(const T& t){}
              void pop() {}
             };

            template<> class Stack<void*>
            {
              void** data;
             public:
              void push(const voidconst& t){}
              void pop(){};
            };

            template<class T>                                        |
            class Stack<T*> : private Stack<void*>          |
            {                                                               |
               typedef Stack<void*> Base;                        |我理解是只產生這么一小段代碼,因為Base是已經特化好了的,所以Base的代碼只有定義一次。
             public:                                                       |如果有個int*的實例的話,那就只要調用Base就行了,不必要再為int* 再生次一次代碼。
               void push(T*  const& t) { Base::push(t);}     |
              void pop(){ Base::pop();}                            |
            };                                                              |


            名字查找問題

            當編譯器首次看到一個模板定義的時候,它不知道有關這個模板的任何信息,只有當它看到模板的實例化時,才能判斷這個模板是否被正確地使用了。 這種情況導致模板的編譯分兩個階段進行。
            第一階段: 解析模板定義,尋找明顯的語法錯誤,解析所有能解析的符號。有些依賴與模板參數的符號就不能解析了。
            第二階段: 編譯器決定是否用模板的一個顯式特化代替基本的模板。



            123
            posted on 2012-05-08 19:23 Dino-Tech 閱讀(255) 評論(0)  編輯 收藏 引用
            国产2021久久精品| 超级碰久久免费公开视频| 国产aⅴ激情无码久久| 7777久久亚洲中文字幕| 四虎影视久久久免费观看| 久久久一本精品99久久精品66| 中文字幕成人精品久久不卡| 99精品国产99久久久久久97| 国产亚州精品女人久久久久久 | 日本福利片国产午夜久久| 欧美久久亚洲精品| 国产精品一久久香蕉产线看| 无码8090精品久久一区| 色综合久久综合网观看| 99re这里只有精品热久久| 伊人久久五月天| 九九久久精品国产| 久久精品成人免费看| 老色鬼久久亚洲AV综合| 久久久久久久97| 久久这里的只有是精品23| 久久国产精品波多野结衣AV | 人人狠狠综合久久亚洲| 女人香蕉久久**毛片精品| 久久久久亚洲av成人网人人软件 | 三级三级久久三级久久| 久久精品夜色噜噜亚洲A∨| 91精品国产高清91久久久久久| 久久久久久久波多野结衣高潮 | 精品久久久久中文字| 香蕉久久一区二区不卡无毒影院| 亚洲精品乱码久久久久久蜜桃图片 | 精品久久人人做人人爽综合| 91精品国产色综久久| 99久久www免费人成精品| 国产午夜精品久久久久九九电影| 久久99精品久久久久久水蜜桃| 国产精品美女久久久免费| 久久精品亚洲乱码伦伦中文| 久久精品综合网| 久久久精品人妻一区二区三区蜜桃|