• <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年4月>
            25262728293031
            1234567
            891011121314
            15161718192021
            22232425262728
            293012345

            常用鏈接

            留言簿

            隨筆分類

            隨筆檔案

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

                 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。
            選擇哪個類模板來進行實例化的規(guī)則遵循“特化程度最高”的原則(半有序)。例:

            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型和其他類型的時候,你會發(fā)現,編譯器在后臺為你復制粘貼了一系列相應的代碼,這使我們的代碼膨脹。解決方法是用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 閱讀(252) 評論(0)  編輯 收藏 引用
            久久精品亚洲AV久久久无码| 青青青国产成人久久111网站| 国产精品女同一区二区久久| 久久99精品免费一区二区| 中文精品久久久久人妻| 久久精品国产亚洲av水果派| 色偷偷888欧美精品久久久| 亚洲国产香蕉人人爽成AV片久久 | 国产精品久久久久国产A级| 国产成人无码久久久精品一| 91精品国产高清久久久久久91| 亚洲综合久久久| 精品乱码久久久久久夜夜嗨| 亚洲精品无码久久一线| 国内精品免费久久影院| 日韩精品无码久久久久久| 国产一区二区三精品久久久无广告| 99久久精品国产一区二区 | 狠狠色丁香久久综合五月| 色婷婷久久久SWAG精品| 国产无套内射久久久国产| 久久精品人成免费| 亚洲精品无码久久久久sm| 亚州日韩精品专区久久久| 国产成人久久精品麻豆一区 | 国产高潮国产高潮久久久91| 午夜天堂精品久久久久| 超级97碰碰碰碰久久久久最新| 久久精品无码一区二区日韩AV| 97超级碰碰碰久久久久| 一本一本久久a久久综合精品蜜桃| 欧美久久久久久午夜精品| 欧美亚洲国产精品久久蜜芽| 久久99国产亚洲高清观看首页| 国产亚洲精品自在久久| 高清免费久久午夜精品| 麻豆一区二区99久久久久| 热re99久久精品国99热| 久久精品国产2020| 亚洲AV乱码久久精品蜜桃| 99久久国产热无码精品免费|