柚子快報(bào)激活碼778899分享:【七】【C++】模版初階
柚子快報(bào)激活碼778899分享:【七】【C++】模版初階
泛型編程
C++中的泛型編程是一種編程范式,它強(qiáng)調(diào)代碼的重用性和類型獨(dú)立性。通過泛型編程,你可以編寫與特定數(shù)據(jù)類型無關(guān)的代碼,使得相同的代碼可以用于多種數(shù)據(jù)類型。
利用重載實(shí)現(xiàn)泛型編程
/*利用重載實(shí)現(xiàn)泛型編程*/
#include
using namespace std;
void Swap(int& left,int& right){
int temp=left;
left=right;
right=temp;
}
void Swap(double& left,double& right){
int temp=left;
left=right;
right=temp;
}
void Swap(char& left,char& right){
int temp=left;
left=right;
right=temp;
}
//...
利用重載實(shí)現(xiàn)泛型編程的缺陷
代碼冗余:
每個(gè)重載函數(shù)需要為每種類型單獨(dú)編寫,這會導(dǎo)致大量類似的代碼。對于每個(gè)新類型,都需要添加一個(gè)新的重載版本,這使得代碼難以維護(hù)。
可擴(kuò)展性差:
如果需要支持新的類型,必須手動添加新的重載函數(shù)。這限制了代碼的可擴(kuò)展性,尤其是對于那些無法預(yù)先知道所有將要使用的類型的情況。
類型檢查不夠靈活:
重載依賴于編譯時(shí)的靜態(tài)類型檢查。這意味著對于泛型代碼,如果類型不匹配,編譯器可能無法找到合適的重載,導(dǎo)致編譯錯(cuò)誤。
運(yùn)行時(shí)效率:
重載函數(shù)通常會產(chǎn)生更多的運(yùn)行時(shí)代碼,因?yàn)槊糠N類型的操作都是獨(dú)立的函數(shù)。
泛型算法實(shí)現(xiàn)困難:
使用重載來實(shí)現(xiàn)真正的泛型算法非常困難。重載需要為每一種可能的類型組合提供一個(gè)實(shí)現(xiàn)。
維護(hù)和調(diào)試?yán)щy:
當(dāng)有許多重載函數(shù)時(shí),維護(hù)和調(diào)試變得更加困難。特別是當(dāng)函數(shù)有多個(gè)參數(shù),且每個(gè)參數(shù)都可能有多種類型時(shí),重載的組合會急劇增加。
模版
在C++中,模板是實(shí)現(xiàn)泛型編程的一種強(qiáng)大工具,允許程序員編寫與數(shù)據(jù)類型無關(guān)的代碼。模板可以分為兩種主要類型:函數(shù)模板和類模板。
函數(shù)模板
函數(shù)模板允許您編寫處理不同類型的通用函數(shù)。它們在編譯時(shí)根據(jù)提供的類型參數(shù)自動實(shí)例化。
/*函數(shù)模版*/
#include
template
T max(T x, T y) {
return (x > y) ? x : y;
}
int main() {
int a = 5, b = 10;
std::cout << "Max of a and b: " << max(a, b) << std::endl;
double c = 3.5, d = 4.5;
std::cout << "Max of c and d: " << max(c, d) << std::endl;
}
template
T max(T x, T y) {
return (x > y) ? x : y;
}
template
在函數(shù)中可以使用T表示數(shù)據(jù)類型,使用函數(shù)時(shí),會自動識別數(shù)據(jù)類型,自動編寫對應(yīng)函數(shù)。
類模板
類模板允許您創(chuàng)建可以處理任何數(shù)據(jù)類型的泛型類。實(shí)例化時(shí),您指定特定的數(shù)據(jù)類型。
/*類模版*/
#include
#include
#include
template
class Stack {
private:
std::vector
public:
void push(T const& elem) {
elements.push_back(elem);
}
void pop() {
if (elements.empty()) {
throw std::out_of_range("Stack<>::pop(): empty stack");
}
elements.pop_back();
}
T top() const {
if (elements.empty()) {
throw std::out_of_range("Stack<>::top(): empty stack");
}
return elements.back();
}
bool empty() const {
return elements.empty();
}
};
int main() {
Stack
intStack.push(7);
std::cout << intStack.top() << std::endl;
}
template
在類中可以使用T表示數(shù)據(jù)類型,使用類的時(shí)候需要再后面加上
Typename關(guān)鍵字
在C++中,關(guān)鍵字 typename 用于泛型編程,尤其是在模板編程中。它的主要作用是指示后續(xù)的標(biāo)識符是一個(gè)類型名。這在兩個(gè)主要場景中非常重要:模板參數(shù)的聲明和模板內(nèi)部的依賴類型名。
模板參數(shù)的聲明
在定義模板時(shí),typename 可用于聲明一個(gè)類型模板參數(shù):
template
class MyClass {
T data;
// ...
};
在這里,typename T 表示 T 是一個(gè)類型參數(shù),這意味著當(dāng)你實(shí)例化 MyClass 時(shí),你可以用任何類型替換 T。
依賴類型名
在模板內(nèi)部,當(dāng)你引用一個(gè)依賴于模板參數(shù)的類型時(shí),你需要在這個(gè)類型前使用 typename 來告訴編譯器它是一個(gè)類型。這通常發(fā)生在模板的成員函數(shù)中:
template
class MyClass {
public:
typename T::SubType method();
};
在這個(gè)例子中,T::SubType 可能是一個(gè)類型,但在模板定義的時(shí)候編譯器并不知道 T 會被什么替換,因此它無法確定 T::SubType 是一個(gè)類型還是其他東西。在這里使用 typename 告訴編譯器 T::SubType 是一個(gè)類型。
關(guān)鍵字 class 與 typename 的可互換性
在模板參數(shù)的聲明中,typename 和 class 關(guān)鍵字是可以互換的,二者意味著相同的事情:
template
class MyClass {
// ...
};
但是在依賴類型名的場景下,只能使用 typename。
模版的原理
編寫模板
當(dāng)你編寫一個(gè)函數(shù)模板時(shí),你實(shí)際上是在定義一個(gè)函數(shù)的藍(lán)圖,而不是一個(gè)具體的、可以直接調(diào)用的函數(shù)。這個(gè)藍(lán)圖告訴編譯器如何生成針對特定類型的函數(shù)實(shí)例。
template
T max(T a, T b) {
return a > b ? a : b;
}
在這個(gè)例子中,T 是一個(gè)占位符,代表任何類型。
編譯器的實(shí)例化過程
當(dāng)你調(diào)用一個(gè)模板函數(shù)時(shí),編譯器會查看你提供的參數(shù)類型,并根據(jù)這些類型,以及函數(shù)模板的定義,生成一個(gè)具體的函數(shù)實(shí)例。這個(gè)過程稱為模板實(shí)例化。
int main() {
auto result = max(5, 10); // 調(diào)用 max
}
在這個(gè)例子中,編譯器看到你用兩個(gè)整數(shù)調(diào)用了 max 函數(shù),所以它生成了一個(gè)接受兩個(gè) int 類型參數(shù)的 max 函數(shù)的實(shí)例。
類型推導(dǎo)
C++11及以后的版本支持自動類型推導(dǎo),這意味著在許多情況下,你不需要顯式指定模板參數(shù)的類型;編譯器可以從函數(shù)調(diào)用中的參數(shù)類型推導(dǎo)出來。
代碼生成
一旦模板實(shí)例化完成,編譯器就會生成與普通函數(shù)相同的機(jī)器碼。這意味著使用函數(shù)模板不會比直接使用針對特定類型編寫的函數(shù)有更多的運(yùn)行時(shí)開銷。
函數(shù)模版實(shí)例化
函數(shù)模板實(shí)例化是一個(gè)編譯時(shí)過程,其中編譯器根據(jù)模板函數(shù)被調(diào)用時(shí)提供的具體類型參數(shù)生成特定的函數(shù)實(shí)例。這個(gè)過程允許程序員編寫一次模板代碼,然后用不同的類型多次實(shí)例化,以適應(yīng)不同的使用場景。
實(shí)例化過程
當(dāng)編譯器遇到一個(gè)模板函數(shù)調(diào)用時(shí),它會檢查提供給函數(shù)模板的實(shí)際類型參數(shù)。然后,編譯器生成一個(gè)新的函數(shù),其中模板參數(shù)被實(shí)際調(diào)用中使用的具體類型所替換。這個(gè)生成的函數(shù)就是模板的一個(gè)實(shí)例。
隱式實(shí)例化
在C++11及更高版本中,函數(shù)模板調(diào)用時(shí)往往不需要顯式指定類型參數(shù)。編譯器能夠根據(jù)傳遞給函數(shù)的參數(shù)自動推導(dǎo)出模板參數(shù)的類型。這使得代碼更簡潔易讀。
/*函數(shù)模版隱式實(shí)例化*/
#include
using namespace std;
template
T Add(const T& left, const T& right) {
return left + right;
}
int main() {
int a1 = 10, a2 = 20;
double d1 = 10.1, d2 = 20.2;
cout << "Add(a1,a2):" << Add(a1, a2) << endl;
cout << "Add(d1,d2):" << Add(d1, d2) << endl;
}
顯式實(shí)例化
雖然編譯器通常能夠自動實(shí)例化函數(shù)模板,但在某些情況下,可能需要或想要顯式地指定模板的實(shí)例化。這可以通過提供模板參數(shù)的具體類型來完成。
/*函數(shù)模版顯示實(shí)例化*/
#include
using namespace std;
template
T Add(const T& left, const T& right) {
return left + right;
}
int main() {
int a1 = 10, a2 = 20;
double d1 = 10.1, d2 = 20.2;
cout << "Add(a1,a2):" << Add
cout << "Add(d1,d2):" << Add
}
函數(shù)模版參數(shù)匹配規(guī)則
1.一個(gè)非模板函數(shù)可以和一個(gè)同名的函數(shù)模板同時(shí)存在,而且該函數(shù)模板還可以被實(shí)例化為這個(gè)非模板函數(shù)。
/*函數(shù)模版顯示實(shí)例化*/
#include
using namespace std;
//通用加法函數(shù)
template
T Add(const T& left, const T& right) {
return left + right;
}
//專門處理int的加法函數(shù)
int Add(const int& left, const int& right) {
return left + right;
}
int main() {
Add(1,2); //與非模版函數(shù)匹配,編譯器不需要特化
Add
}
2.對于非模板函數(shù)和同名函數(shù)模板,如果其他條件都相同,在調(diào)動時(shí)會優(yōu)先調(diào)用非模板函數(shù)而不會從該模板產(chǎn)生出一個(gè)實(shí)例。如果模板可以產(chǎn)生一個(gè)具有更好匹配的函數(shù), 那么將選擇模板。
/*函數(shù)模版精準(zhǔn)匹配或生成匹配的函數(shù)*/
#include
using namespace std;
//通用加法函數(shù)
template
T Add(const T& left, const T& right) {
return left + right;
}
//專門處理int的加法函數(shù)
int Add(const int& left, const int& right) {
return left + right;
}
int main() {
Add(1, 2); //與非模版函數(shù)匹配,編譯器不需要特化
Add(1, 2.1); //模版函數(shù)可以生成更加匹配的版本,編譯器根據(jù)實(shí)參生成更加匹配的Add函數(shù)
}
3.模板函數(shù)不允許自動類型轉(zhuǎn)換,但普通函數(shù)可以進(jìn)行自動類型轉(zhuǎn)換
類模版實(shí)例化
類模板實(shí)例化是C++中一種創(chuàng)建具體類從泛型類模板的過程。類模板通過允許類型作為參數(shù),提供了一種強(qiáng)大的方式來編寫靈活且可重用的代碼。實(shí)例化過程中,模板參數(shù)被具體的類型替換,從而生成一個(gè)特定類型的類定義。
template
class Box {
public:
T contents;
Box(T newValue) : contents(newValue) {}
void show() const {
std::cout << contents << std::endl;
}
};
隱式實(shí)例化
在使用類模板時(shí),你可以讓編譯器通過構(gòu)造函數(shù)或方法的參數(shù)類型來自動推導(dǎo)模板參數(shù)類型。
Box box1(123); // 隱式實(shí)例化為 Box
Box box2("C++"); // 隱式實(shí)例化為 Box
顯式實(shí)例化
也可以顯式地指定模板參數(shù)的類型,明確地告訴編譯器你想要實(shí)例化的具體類型。
Box
Box
使用實(shí)例化的類
一旦類模板被實(shí)例化,就可以像使用任何其他普通類一樣使用它。你可以創(chuàng)建對象,調(diào)用方法等。
box1.show(); // 顯示:123
box2.show(); // 顯示:C++
結(jié)尾
最后,感謝您閱讀我的文章,希望這些內(nèi)容能夠?qū)δ兴鶈l(fā)和幫助。如果您有任何問題或想要分享您的觀點(diǎn),請隨時(shí)在評論區(qū)留言。
同時(shí),不要忘記訂閱我的博客以獲取更多有趣的內(nèi)容。在未來的文章中,我將繼續(xù)探討這個(gè)話題的不同方面,為您呈現(xiàn)更多深度和見解。
謝謝您的支持,期待與您在下一篇文章中再次相遇!
柚子快報(bào)激活碼778899分享:【七】【C++】模版初階
參考文章
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場。
轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。


