27、C++ Primer 4th 筆記,模板與泛型程式設計(2)

來源:互聯網
上載者:User

1、當函數的傳回值必須與形參表中所用的所有類型都不同時,有必要覆蓋模板實參推斷機制,顯式指定為模板形參所用的類型或值。

樣本

sum(static_cast<int>(s), i);

2、指定傳回型別的一種方式是引入第三個模板實參:

樣本

template <class T1, class T2, class T3>T1 sum(T2, T3);// poor design: Users must explicitly specify all three template parameterstemplate <class T1, class T2, class T3>T3 alternative_sum(T2, T1);int main(){// ok T1 explicitly specified; T2 and T3 inferred from argument typeslong val3 = sum<long>(i, lng); // ok: calls long sum(int, long)// error: can't infer initial template parameterslong val3 = alternative_sum<long>(i, lng);// ok: All three parameters explicitly specifiedlong val2 = alternative_sum<long, int, long>(i, lng);return 1;}

    為調用提供顯式模板實參與定義類模板的執行個體很類似。顯式模板實參從左至右對應模板形參相匹配,第一個模板實參與第一個模板形參匹配,依次類推。假如可以從函數形參推斷,則結尾(最右邊)形參的顯式模板實參可以省略

3、函數模板的指標賦值

樣本

template <typename T> int compare(const T&, const T&);// overloaded versions of func; each take a different function pointer typevoid func(int(*) (const string&, const string&));void func(int(*) (const int&, const int&));func(compare<int>); // ok: explicitly specify which version of compare

4、模板編譯模型

1)包含編譯模型

    在這種模型中,編譯器必須能看到用到的所用模板的定義。它依賴於模板定義被包含在每個使用模板的檔案中。一般而言,模板定義儲存在一個標頭檔中,使用模板的任意檔案必須包含該檔案。

2)分別編譯模型

    編譯器用來尋找模板定義的機制,它允許將模板定義和聲明儲存在獨立的檔案中。模板聲明放在一個標頭檔中,而定義只在程式中出現一次

通過export關鍵字來實現這種機制。export是用來指出編譯器必須記住相關模板定義位置的關鍵字。export 關鍵字一般與函數定義一起出現(聲明不必指定export,標頭檔中的類定義體不應該使用export,如果在標頭檔中使用了export,則該標頭檔只能被程式中一個源檔案使用),類通常在相關類實現檔案中聲明為export。在一個程式中,一個模板只能用 export 關鍵字定義一次。

匯出類的成員自動為匯出的。也可以將類模板的個別成員聲明為匯出的。任意非匯出成員函數的定義必須像在包含模型中一樣:定義應放在定義類模板的標頭檔中。

樣本

// class template header goes in shared header filetemplate <class Type> class Queue { //... };// Queue.cc implementation file declares Queue as exportedexport template <class Type> class Queue;#include "Queue.h"// Queue member definitions

5、通常,當使用類模板的名字的時候,必須指定模板形參。這一規則有個例外:在類本身的範圍內部,可以使用類模板的非限定名。例如,在預設建構函式和

複製建構函式的聲明中,名字 Queue 是 Queue<Type> 縮寫表示。實質上,編譯器推斷,當我們引用類的名字時,引用的是同一版本。

編譯器不會為類中使用的其他模板的模板形參做這樣的推斷。

6、在類外定義的成員函數

樣本

template <class T> ret-type Queue<T>::member-name;

類模板的成員函數本身也是函數模板。與其他函數模板不同的是,在執行個體化類模板成員函數的時候,編譯器不會執行模板實參推斷。

非類型模板實參必須是編譯時間常量運算式。

7、類模板中的友元聲明

三種:

1)普通非模板類或函數的友元聲明,將友元關係授予明確指定的類或函數。

2)類模板或函數模板的友元聲明,授予對友元所有執行個體的訪問權。

3)只授予對類模板或函數模板的特定執行個體的訪問權的友元聲明。

樣本

{//...//the first situationfriend class FooBar;friend void fcn();//the second situationtemplate <class T> friend class Foo1;template <class T> friend void templ_fcn1(const T&);//the third situationfriend class Foo2<char*>;friend void templ_fcn2<char*>(char* const &);//...}//下面形式的友元更為常見:template <class T> class Foo3;template <class T> void templ_fcn3(const T&);template <class Type> class Bar {// each instantiation of Bar grants access to the// version of Foo3 or templ_fcn3 instantiated with the same typefriend class Foo3<Type>;friend void templ_fcn3<Type>(const Type&);// ...};Bar<int> bi; // Foo3<int> and templ_fcn3<int> are friendsBar<string> bs; // Foo3<string>, templ_fcn3<string> are friends

    上例中,,Foo3<int> 可以訪問 Bar<int> 的私人部分,但不能訪問

Bar<string> 或者任意其他 Bar 執行個體的私人部分。

聲明的依賴性:

當授予對給定模板的執行個體的訪問權時候,在範圍中不需要存在該類模板或函數模板的聲明。實質上,編譯器將友元聲明也當作類或函數的聲明對待。想要限制對特定執行個體化的友元關係時,必須在可以用於(can use)友元聲明之前聲明類或函數。

範例程式碼

template <class T> class A;template <class T> class B {public:friend class A<T>; // ok: A is known to be a templatefriend class C; // ok: C must be an ordinary, nontemplate classtemplate <class S> friend class D; // ok: D is a templatefriend class E<T>; // error: E wasn't declared as a templatefriend class F<int>; // error: F wasn't declared as a template};

    如果沒有事先告訴編譯器該友元是一個模板,則編譯器將認為該友元是一個普通非模板類或非模板函數。

8、任意類(模板或非模板)可以擁有本身為類模板或函數模板的成員,這種成員成員稱為成員模板,成員模板不能為虛。

9、當成員模板是類模板的成員時,它的定義必須包含類模板形參以及自己的模板形參。

範例程式碼

template <class T> template <class Iter>void Queue<T>::assign(Iter beg, Iter end){//destroy(); // remove existing elements in this Queue//copy_elems(beg, end); // copy elements from the input range}

10、成員模板遵循常規存取控制。

11、成員模板函數有兩種模板形參:由類定義的和由成員模板本身定義。類模板形參由調用函數的對象的類型確定;成員定義的模板形參的行為與普通函數模板一樣,通過常規模板實參推斷而確定。

12、模板類的每個執行個體化都有自己的static成員。與任意其它成員函數一樣,static成員函數只有在程式中使用時才進行執行個體化。像使用任意其他static資料成員一樣,必須在類外部出現資料成員的定義。

樣本

template <class T>size_t Foo<T>::ctr = 0; // define and initialize ctr

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.