天天看點

c++模闆入門,泛型程式設計、函數模闆、類模闆

目錄

1. 泛型程式設計

2. 函數模闆

2.1 函數模闆概念

2.2函數模闆格式

2.3 函數模闆的原理

2.4 函數模闆的執行個體化

2.5 模闆參數的比對原則

3. 類模闆

3.1 類模闆的定義格式

3.2 類模闆的執行個體化

1. 泛型程式設計

如何實作一個通用的交換函數?

使用函數重載雖然可以實作,但是有一下幾個不好的地方:

1. 重載的函數僅僅隻是類型不同,代碼的複用率比較低,隻要有新類型出現時,就需要增加對應的函數

2. 代碼的可維護性比較低,一個出錯可能所有的重載均出錯

泛型程式設計:編寫與類型無關的通用代碼,是代碼複用的一種手段。模闆是泛型程式設計的基礎。

2. 函數模闆

2.1 函數模闆概念

函數模闆代表了一個函數家族,該函數模闆與類型無關,在使用時被參數化,根據實參類型産生函數的特定類型版本。

2.2函數模闆格式

template<typename T1, typename T2,......,typename Tn>

傳回值類型 函數名(參數清單){}

template<typename T>
void Swap( T& left, T& right) { T temp = left;
left = right;
right = temp; }
           

注意:typename是用來定義模闆參數關鍵字,也可以使用class(切記:不能使用struct代替class)

2.3 函數模闆的原理

在編譯器編譯階段,對于模闆函數的使用,編譯器需要根據傳入的實參類型來推演生成對應類型的函數以供調用。比如:當用double類型使用函數模闆時,編譯器通過對實參類型的推演,将T确定為double類型,然後産生一份專門處理double類型的代碼,對于字元類型也是如此。

2.4 函數模闆的執行個體化

用不同類型的參數使用函數模闆時,稱為函數模闆的執行個體化。模闆參數執行個體化分為:隐式執行個體化和顯式執行個體化。

1. 隐式執行個體化:讓編譯器根據實參推演模闆參數的實際類型

2. 顯式執行個體化:在函數名後的<>中指定模闆參數的實際類型

如果類型不比對,編譯器會嘗試進行隐式類型轉換,如果無法轉換成功編譯器将會報錯。

2.5 模闆參數的比對原則

1. 一個非模闆函數可以和一個同名的函數模闆同時存在,而且該函數模闆還可以被執行個體化為這個非模闆函數

2. 對于非模闆函數和同名函數模闆,如果其他條件都相同,在調動時會優先調用非模闆函數而不會從該模闆産生出一個執行個體。如果模闆可以産生一個具有更好比對的函數,那麼将選擇模闆。

3. 模闆函數不允許自動類型轉換,但普通函數可以進行自動類型轉換

3. 類模闆

3.1 類模闆的定義格式

template<class T1, class T2, ..., class Tn>
class 類模闆名
{
// 類内成員定義
};
           

3.2 類模闆的執行個體化

類模闆執行個體化與函數模闆執行個體化不同,類模闆執行個體化需要在類模闆名字後跟<>,然後将執行個體化的類型放在<>中即可,類模闆名字不是真正的類,而執行個體化的結果才是真正的類。

// Vector類名,Vector<int>才是類型
Vector<int> s1;
s1.PushBack(1);
s1.PushBack(2);
s1.PushBack(3);
Vector<double> s2;
s2.PushBack(1.0);
s2.PushBack(2.0);
s2.PushBack(3.0);
for(size_t i = 0; i < s1.Size(); ++i) {
cout<<s1[i]<<" "; }
cout<<endl;
for(size_t i = 0; i < s2.Size(); ++i) {
cout<<s2[i]<<" "; }
cout<<endl;
           

繼續閱讀