• <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 閱讀(252) 評論(0)  編輯 收藏 引用
            性高湖久久久久久久久| 中文字幕久久亚洲一区| 国产精品久久自在自线观看| 93精91精品国产综合久久香蕉| 色诱久久av| 久久亚洲精品视频| 久久无码人妻一区二区三区| 久久播电影网| 亚洲国产精品久久66| 青青草原综合久久大伊人导航| 亚洲av伊人久久综合密臀性色| 国产精品久久国产精麻豆99网站| 国产精品亚洲综合专区片高清久久久 | 国产精品久久久久久久久免费| 99精品久久久久久久婷婷| 2021最新久久久视精品爱| 久久亚洲高清综合| 性欧美大战久久久久久久| 99久久综合狠狠综合久久止| 偷窥少妇久久久久久久久| 久久久久九国产精品| 久久人人爽人人爽人人片AV东京热| 亚洲午夜久久久久久久久久| 久久天天躁狠狠躁夜夜avapp | 久久久久久国产精品美女| 亚洲精品综合久久| 青青草原综合久久| 国产一区二区精品久久| 久久99精品国产99久久6| 精品久久久久久无码专区不卡 | 国产精自产拍久久久久久蜜| 久久亚洲欧美国产精品| 精品久久久中文字幕人妻| 久久精品人人做人人爽电影 | 综合久久国产九一剧情麻豆| 手机看片久久高清国产日韩 | 伊人色综合久久天天人守人婷| 精品久久久久久国产牛牛app | 久久综合狠狠综合久久| 一本色道久久99一综合| 久久丫精品国产亚洲av|