網(wǎng)站首頁 編程語言 正文
一、泛型編程
我們前面已經(jīng)學(xué)過函數(shù)的重載,實現(xiàn)了在函數(shù)名相同的情況下,實現(xiàn)不同的功能!
例如:
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;
}
利用函數(shù)重載雖然實現(xiàn)了“通用”的交換函數(shù),但是會有以下問題:
- 重載的函數(shù)僅僅是類型不同,代碼復(fù)用率低,只要有新的類型時,有需要用戶自己增加新的重載函數(shù)。
- 代碼的可維護性低,一個出錯可能所有的重載都出錯。
??????:在C++中是否存在一個模具,通過給這個模具中填充不同的材料(類型),來獲得不同的鑄件(即生成具體的代碼)。
泛型編程:編寫與類型無關(guān)的通用代碼,是代碼復(fù)用的一種的手段。模板是泛型編程的基礎(chǔ)。
二、函數(shù)模板
2.1、函數(shù)模板的概念
函數(shù)模板代表了一個函數(shù)家族,該函數(shù)模板與類型無關(guān),在使用時被參數(shù)化,根據(jù)實參類型產(chǎn)生函數(shù)的特定類型版本。
2.2、函數(shù)模板的格式
template<typename T1, typename T2,…,typename Tn>
返回值類型 函數(shù)名(參數(shù)列表){}
template<typename T>
void Swap(T& left, T& right)
{
T temp = left;
left = right;
right = temp;
}
??注意:typename 是用來定義函數(shù)模板參數(shù)關(guān)鍵字的,也可以用class,但是不可以用struct。
2.3、函數(shù)模板的原理
函數(shù)模板我們可以理解為一個藍圖,它本身并不是函數(shù),在編譯器編譯階段根據(jù)傳入的實參類型來推演生成對應(yīng)類型的函數(shù)以供調(diào)用,也叫做函數(shù)模板的實例化。
2.4、函數(shù)模板的實例化
用不同類型的對象使用函數(shù)模板時,稱為函數(shù)模板的實例化。模板參數(shù)實例化分為隱式實例化和顯示實例化。
2.4.1、隱式實例化
讓編譯器根據(jù)實參推演模板參數(shù)的實際類型。
template<class T>
T Add(const T& left, const T& right)
{
return left + right;
}
int main(){
int a1 = 10, a2 = 20;
double d1 = 10.0, d2 = 20.0;
Add(a1, a2);
Add(d1, d2);
//Add(a1, d1);
Add(a1, (int)d1);
system("pause");
return 0;
}
2.4.2、顯示實例化
讓函數(shù)名后的<>中指定模板參數(shù)的實際類型。
int main(){
int a = 10;
double b = 20.0;
//Add(a, (int)b);//隱式
Add<int>(a, b);//顯示
system("pause");
return 0;
}
Add(a, b);目的在于如果類型不匹配,編譯器會嘗試進行隱式類型轉(zhuǎn)換,如果無法轉(zhuǎn)換成功編譯器將會報錯。
三、類模板
3.1、類模板的定義格式
template<typename T1, typename T2,…,typename Tn>
class 類模板名
{
//類內(nèi)成員
};
3.1、類模板的實例化
類模板實例化與函數(shù)模板實例化不同,類模板實例化傳的是類型,而函數(shù)模板實例化傳的是對象,類模板實例化需要在類模板名字后面跟上<>,然后將實例化類型放在<>中即可!
vector<int> s1;
??:與普通類不同,這里vector是類名,而vector才是類型。
四、模板的特化
4.1、概念
通常情況下,我們使用模板可以實現(xiàn)一些與類型無關(guān)的代碼,但是對于一些特殊類型可能會得到一些錯誤的結(jié)果,需要特殊處理。
template<class T>
bool Less(T left, T right){
return left < right;
}
//特化
template<>
bool Less<Date*>(Date* p1, Date* p2)
{
cout << "調(diào)用的模板函數(shù)的特化" << endl;
return *p1 < *p2;
}
//只要是指針 都可以調(diào)用這個,這個思想很重要
//偏特化的帶限制條件(指針類型可調(diào))
template<class T>
bool Less(T* left, T* right)
{
cout << "調(diào)用的函數(shù)模板" << endl;
return *left < *right;
}
代碼解釋:當(dāng)我們在實參部分傳的是Date型指針的時候,如果不特化處理,結(jié)果會出錯。
上述就是在原模板的基礎(chǔ)上針對特殊類型所進行特殊化的實現(xiàn)方式。模板特化中分為函數(shù)模板特化和類模板特化。
4.2、函數(shù)模板特化步驟
- 必須要先有一個基礎(chǔ)的函數(shù)模板。
- 關(guān)鍵字template后面接一隊空的<>。
- 函數(shù)名后跟一對<>,尖括號中指定需要特化的類型。
- 函數(shù)形參表:必須要和模板函數(shù)的基礎(chǔ)參數(shù)類型完全相同,如果不同編譯器可能會報一些奇怪的錯誤。
template<class T>
bool Less(T left, T right){
return left < right;
}
//特化
template<>
bool Less<Date*>(Date* p1, Date* p2)
{
cout << "調(diào)用的模板函數(shù)的特化" << endl;
return *p1 < *p2;
}
4.3、類模板的特化
4.3.1、全特化
全特化就是將模板參數(shù)中所有的參數(shù)都確定化
//類模板
template<class T1, class T2>
class data
{
public:
data(T1 a, T2 b)
:_a(a)
, _b(b)
{
cout << "data<T1, T2>" << endl;
}
private:
T1 _a;
T2 _b;
};
//全特化
template<>
class data <int, char>
{
public:
data(int a, char b)
:_a(a)
, _b(b)
{
cout << "全特化data<int, char>" << endl;
}
private:
int _a;
char _b;
};
int main()
{
data<int, int> s1(1, 2);
data<int, char> s2(1, 'a');
}
4.3.2、偏特化
偏特化:任何針對模板參數(shù)進一步進行條件限制設(shè)計的特化版本。比如對一下類模板:
//類模板
template<class T1, class T2>
class data{
public:
data(T1 a, T2 b)
:_a(a)
, _b(b)
{
cout << "data<T1, T2>" << endl;
}
private:
T1 _a;
T2 _b;
};
??????偏特化有以下兩種變現(xiàn)方式:
部分特化:將模板參數(shù)中的一部分參數(shù)特化
//半特化
// 1、將模板參數(shù)類表中的一部分參數(shù)特化。
template<class T1>
class data<T1, char> {
public:
data(T1 a, char b)
:_a(a)
, _b(b)
{
cout << "偏特化data<T1, char>" << endl;
}
private:
T1 _a;
char _b;
};
參數(shù)進一步限制:偏特化并不僅僅是指特化部分參數(shù),而是針對模板參數(shù)更進一步的條件限制所設(shè)計出來的特化版本。
// 2、偏特化并不僅僅是指特化部分參數(shù),而是針對模板參數(shù)更進一步的條件限制所設(shè)計出來的一個特化版本。
template<class T1, class T2>
class data <T1*, T2* > {
public:
data(T1 a, char b)
:_a(a)
, _b(b)
{
cout << "Data<T1*, T2*>" << endl;
}
private:
T1 _a;
T2 _b;
};
template<class T1, class T2>
class data<T1&, T2&>
{
public:
data(const T1& a, const T2& b)
:_a(a)
, _b(b)
{ cout << "Data<T1&, T2&>" << endl; }
private:
const T1& _a;
const T2& _b;
};
int main(){
data<char*, char*> s6(1,2);
data<int&, int&> s7(1, 2);
system("pause");
return 0;
}
代碼解釋:
- 第一個是兩個參數(shù)特例化為指針類型(只要傳的是指針,就走對應(yīng)的)。
- 第二個是兩個參數(shù)特例化為引用類型。
原文鏈接:https://blog.csdn.net/qq_43727529/article/details/125837145
相關(guān)推薦
- 2022-07-08 C語言完整實現(xiàn)12種排序算法(小結(jié))_C 語言
- 2022-09-18 Python?Pandas實現(xiàn)DataFrame合并的圖文教程_python
- 2023-04-26 React使用PropTypes實現(xiàn)類型檢查功能_React
- 2022-06-30 React-hooks中的useEffect使用步驟_React
- 2022-12-05 Django中使用AJAX的詳細(xì)過程_python
- 2022-02-11 element ui table 內(nèi)嵌 input 調(diào)用 focus 方法無效
- 2023-03-13 Android自定義Toast樣式實現(xiàn)方法詳解_Android
- 2022-06-02 Android?Apk反編譯及加密教程_Android
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支