C++實現一個通用的加法函數

1. 使用函數重載

【缺陷】

只要有新類型出現,就要重新添加對應函數

除類型外,所有函數的函數體都相同,代碼的複用率不高

如果函數只是返回值類型不同,函數重載不能解決

一個方法有問題,所有的方法都有問題,不好維護

2. 使用公共基類  

【缺陷】 

 -藉助公共基類來編寫通用代碼,將失去類型檢查的優點

  -對於以後實現的許多類,都必須繼承自某個特定的基類,代碼維護更加困難

3. 使用宏函數  

【缺陷】

不是函數,不進行類型檢測,安全性不高,表達式複雜容易出錯

那還有什麼其他方式嗎? 能否將寫代碼的規則告訴編譯器,讓編譯器來實現呢?、

4. 泛型編程

編寫與類型無關的邏輯代碼,是代碼複用的一種手段。模板是泛型編程的基礎 

函數模板

1. 概念  函數模板代表了一個函數家族,該函數模板與類型無關,在使用時被參數化,根據實參類型產生函數的特定類型版本2. 函數模板格式

template  </typename t1, typename t2,......,class tn>

返回值類型 函數名(參數列表(參數如果有多個,每一個前都要加 typename 或 class, 用逗號隔開)){}

template<typename T>
T Add(const T& left, const T& right)
{
	return left + right;
}

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

函數模板還可以被定義爲inline類型的:

template<class T>
inline T Add(const T& left, const T& right)
{
 return left + right;
} 

注意:inline關鍵字必須放在模板形參表之後,返回值之前,不能放在template之前。

3. 函數模板實例化&參數推演  

模板是一個藍圖,它本身不是類或者函數,編譯器用模板產生指定的類或者函數的特定類型版本,產生模板特定類型的過程稱爲函數模板實例化

#include<iostream>
using namespace std;

template<typename T>//相當於聲明瞭 T 這樣一個類型

inline T Add(const T& left, const T& right)
{
	cout << typeid(left).name() << endl;
	return left + right;
}

int main()
{
	//模板函數的隱式實例化(需要根據參數的類型去推演 T 的類型)
	Add(1, 2);
	Add(1.0, 2.0);
	Add('1', '2');
	//Add(1, '1');//報錯: 模板 T 類型不明確
	//模板函數的顯式實例化,已經明確指定了 T 的類型
	Add<int>(1, '1');//相當於明確指定了模板裏面的 T 爲 int,會把字符類型'1'轉換爲 int 類型的 1
 	return 0;
}

輸出結果:

真正意義上的 Add 函數的原型

int ---> Add<int>

double--->Add<double>

char--->Add<char>

注意:模板函數的編譯分兩個階段

實例化之前,檢查模板代碼本身,是否出現簡單語法錯誤,如:模板參數列表少了 typename

在實例化後,檢查模板生成的代碼,是否所有的調用都有效,如:實例化類型不支持某些函數調用

從函數實參確定模板形參類型和值的過程稱爲模板實參推演,多個類型形參的實參必須完全匹配

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章