• <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年5月>
            293012345
            6789101112
            13141516171819
            20212223242526
            272829303112
            3456789

            常用鏈接

            留言簿

            隨筆分類

            隨筆檔案

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

                 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 閱讀(253) 評論(0)  編輯 收藏 引用
            亚洲中文字幕久久精品无码喷水| 青青青青久久精品国产h| 久久夜色撩人精品国产小说| 久久久久国产精品麻豆AR影院| 欧美亚洲国产精品久久高清| 久久久久亚洲精品无码蜜桃| 久久久久国产视频电影| 久久久久久亚洲Av无码精品专口| 91精品国产91久久久久久蜜臀 | 亚洲精品国产字幕久久不卡 | 久久九九兔免费精品6| www.久久热.com| 久久WWW免费人成一看片| 国产69精品久久久久99| 久久精品国产亚洲AV无码娇色| 欧美日韩中文字幕久久久不卡| 国产成人精品久久免费动漫 | 久久久久国产| 青青草国产精品久久| 亚洲午夜久久久影院| 久久最新免费视频| 91久久国产视频| 国产精品久久久久无码av| 99蜜桃臀久久久欧美精品网站| 久久九九久精品国产免费直播| 99久久精品影院老鸭窝| 日韩精品久久久肉伦网站| 亚洲精品无码久久毛片| 久久强奷乱码老熟女| 久久精品亚洲欧美日韩久久| 国产激情久久久久影院老熟女| 国产一区二区三区久久精品| 久久精品国产亚洲av影院| 性欧美大战久久久久久久久| 蜜臀av性久久久久蜜臀aⅴ麻豆| 久久国产劲爆AV内射—百度| 中文字幕乱码人妻无码久久| 中文字幕无码精品亚洲资源网久久| 久久婷婷色综合一区二区| 亚洲午夜久久久久久久久久 | 久久久噜噜噜久久|