• <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++ 第二卷第五章的內(nèi)容,先從模板的特化說起。模板的內(nèi)容太豐富了,學習是一回事,要掌握模板肯定要在工作中經(jīng)常使用。

            模板特化

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

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


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

            半特化(偏特化)
            沒有完全特化成特定的類型,特化的不完全體,還保留其他可能性。例:
            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;
            }

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


            防止代碼膨脹

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

            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ā)現(xiàn),編譯器在后臺為你復(fù)制粘貼了一系列相應(yīng)的代碼,這使我們的代碼膨脹。解決方法是用void*進行完全特化,然后從void* 實現(xiàn)中派生出所有其他的指針類型。

            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;                        |我理解是只產(chǎn)生這么一小段代碼,因為Base是已經(jīng)特化好了的,所以Base的代碼只有定義一次。
             public:                                                       |如果有個int*的實例的話,那就只要調(diào)用Base就行了,不必要再為int* 再生次一次代碼。
               void push(T*  const& t) { Base::push(t);}     |
              void pop(){ Base::pop();}                            |
            };                                                              |


            名字查找問題

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



            123
            posted on 2012-05-08 19:23 Dino-Tech 閱讀(255) 評論(0)  編輯 收藏 引用
            奇米影视7777久久精品| 久久精品国产亚洲精品| 亚洲av日韩精品久久久久久a| 亚洲AV乱码久久精品蜜桃| 国产精品无码久久久久久| 久久综合九色综合97_久久久| 久久久久国产一级毛片高清板| 狠狠综合久久综合88亚洲| 狠狠色丁香久久综合五月| 亚洲欧美久久久久9999| 久久精品国产第一区二区三区| 久久精品国产亚洲7777| 欧美一区二区三区久久综| 狠狠色伊人久久精品综合网 | 97精品依人久久久大香线蕉97| 国产精品福利一区二区久久| 国产69精品久久久久APP下载| 久久久91精品国产一区二区三区| 久久综合色老色| 欧洲性大片xxxxx久久久| 久久夜色精品国产亚洲| 久久99国内精品自在现线| 97精品伊人久久久大香线蕉| 品成人欧美大片久久国产欧美| 久久久久亚洲AV成人片| 99久久精品国产一区二区 | 久久久久久精品无码人妻| 精品久久久久久无码人妻热| 久久se精品一区二区| av午夜福利一片免费看久久| 久久国产劲爆AV内射—百度| 一本久久免费视频| 伊人久久亚洲综合影院| 亚洲国产婷婷香蕉久久久久久| 久久人妻少妇嫩草AV蜜桃| 久久精品国产亚洲AV不卡| 久久国产福利免费| 久久国产一片免费观看| 人人妻久久人人澡人人爽人人精品| 日本免费一区二区久久人人澡 | 国产视频久久|