天天看點

函數模闆--C++模闆的參數

引出

當在C++中要實作一個通用的交換函數, 因如何實作

void Swap(int& left, int& right) 
{    
	int temp = left;    
	left = right;   
	right = temp; 
}
 
void Swap(double& left, double& right) 
{
    double temp = left;
    left = right;
    right = temp; 
}
 
void Swap(char& left, char& right) 
{    
	char temp = left;
    left = right;
    right = temp;
}
......
           

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

  1. 重載的函數僅僅隻是類型不同,代碼的複用率比較低,隻要有新類型出現時,就需要增加對應的函數
  2. 代碼的可維護性比較低,一個出錯可能所有的重載均出錯

使用模闆, 相當于告訴編譯器一個模子, 就能節省很多代碼

模闆分為函數模闆和類模闆

函數模闆

示例:

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

這樣就能實作多種基本類型的交換, 調用方法與一般的函數相同, 編譯器會自己産生相關代碼

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

類模闆

格式:

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

類模闆的使用參見: 類模闆的使用

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

模闆的參數

上面能看到模闆的參數如下

template< class T>

實際上模闆的參數多種多樣, 模闆參數分為:

  1. 類型形參即:出現在模闆參數清單中,跟在class或者typename之類的參數類型名稱。
  2. 非類型形參,就是用一個常量作為類(函數)模闆的一個參數,在類(函數)模闆中可将該參數當成常量來使用。
template<class T, size_t N = 10>   
class array   
{ 
private:
        T _array[N];        
        size_t _size;    
...
} 
           

當定義數組時, 數組的長度一般必須傳一個常量值, 不能傳變量

使用非類型形參就能夠傳數組的長度

注意:

  1. 浮點數、類對象以及字元串是不允許作為非類型模闆參數的。
  2. 非類型的模闆參數必須在編譯期就能确認結果。

模闆的特化

通常情況下,使用模闆可以實作一些與類型無關的代碼,但對于一些特殊類型的可能會得到一些錯誤的結 果,比如:

函數模闆特化

template<class T> 
bool IsEqual(T& left, T& right) 
{    return left == right; }
 
void Test() 
{    char* p1 = "hello";    
	char* p2 = "world";
 
    if(IsEqual(p1, p2))
        cout<<p1<<endl; 
    else       
        cout<<p2<<endl; 
}
           

此時,就需要對模闆進行特化。即:在原模闆類的基礎上,針對特殊類型所進行特殊化的實作方式。模闆特 化中分為函數模闆特化與類模闆特化

函數模闆的特化步驟:

  1. 必須要先有一個基礎的函數模闆
  2. 關鍵字template後面接一對空的尖括号<>
  3. 函數名後跟一對尖括号,尖括号中指定需要特化的類型
  4. 函數形參表: 必須要和模闆函數的基礎參數類型完全相同,如果不同編譯器可能會報一些奇怪的錯誤
template<> 
bool IsEqual<char*>(char*& left, char*& right) 
{    if(strcmp(left, right) > 0)        
		return true;        
	return false; 
}
           

類模闆特化

template<class T1, class T2> 
class Data 
{ 
public:    
	Data() {cout<<"Data<T1, T2>" <<endl;} 
private:    
	T1 _d1;   
	T2 _d2; 
};
 
template<> 
class Data<int, char> 
{
 public:    
 	Data() {cout<<"Data<int, char>" <<endl;} 
 private:    
 	T1 _d1;    
 	T2 _d2; 
 };
 
void TestVector() 
{    
	Data<int, int> d1;   
	Data<int, char> d2; 
}
           

當然也可以隻特化一個參數, 叫偏特化

總結

優點:

  1. 模闆複用了代碼,節省資源,更快的疊代開發,C++的标準模闆庫(STL)是以而産生
  2. 增強了代碼的靈活性

缺點:

  1. 模闆會導緻代碼膨脹問題,也會導緻編譯時間變長
  2. 出現模闆編譯錯誤時,錯誤資訊非常淩亂,不易定位錯誤

繼續閱讀