這是關于一個普通雙非本科大一學生的C++的學習記錄貼
在此前,我學了一點點C語言還有簡單的數據結構,如果有小伙伴想和我一起學習的,可以私信我交流分享學習資料
那么開啟正題
今天分享的是關于模板的知識點
1.非類型模板參數
模板參數分為類型形參和非類型形參
類型形參:出現在模板參數列表中,跟在class或者typename后面的參數形參名稱
非類型形參:用一個常量作為類(函數)模板的一個參數,在類(函數)中可將參數當成常量來使用
這里定義一個模板類型的靜態數組給出示范
namespace wkl
{// 定義一個模板類型的靜態數組template<class T, size_t N = 10>// T 類型模板參數 N 非類型模板參數class array{public:T& operator[](){}const T& operator[](){}private:T _arrry[N];size_t _size;};
}
注意:
1.只有整形家族允許作為非類型模板參數
2.非類型模板參數必須在編譯期就能確定結果
2.模板的特化
2.1概念
通常情況下,使用模板可以實現一些與類型無關的代碼,但對于一些特殊類型的可能會得到一些錯誤的結果,需要特殊處理
我們來看下面的代碼
template<class T>
bool my_less(const T& left, const T& right)
{return left < right;
}void Test1()
{cout << my_less(1, 2) << endl;string s1("hehe");string s2("hehe");cout << my_less(s1, s2) << endl;
}
創建一個比較大小的模板函數,很顯然對于整形家族,浮點家族它都是正確的,而對于string等類,它就需要我們來特化
由此我們引出特化的概念:
在原模板類的基礎上,針對特殊類型進行特殊化處理的實現方式,模板特化中分為函數模板特化與類模板特化
2.2函數模板特化
函數模板特化步驟:
1.必須要有一個基礎的函數模板
2.關鍵字template后面接一對空的尖括號
3.函數名后跟一對尖括號,尖括號中指定需要特化的類型
4.函數形參表:必須要和模板函數的基礎參數類型完全相同,如果不同編譯器可能會報一些奇怪的錯誤
template<class T>
bool my_less(const T left, const T right)
{return left < right;
}template<>
bool my_less<string>(const string left, const string right)
{return strcmp(left.c_str(), right.c_str()) == 0;
}void Test1()
{cout << my_less(1, 2) << endl;string s1("hehe");string s2("hehe");cout << my_less(s1, s2) << endl;
}
這樣改造之后,模板函數對于string就生成了正確的特化版本
注意:
一般情況下,如果函數模板遇到不能處理或者處理有誤的類型,為了實現簡單,通常都是將函數直接給出,遇到類型匹配的函數,就不會用模板再實例化一份代碼,而是直接調用可匹配的
2.3類模板特化
2.3.1全特化
全特化是將模板參數列表中所有參數都確定化
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:int _d1;char _d2;
};void Test2()
{Data<int, int> d1;Data<char, char> d2;Data<int, char> d3;Data<char, int> d4;
}
2.3.2偏特化
偏特化:任何針對模板參數進一步進行條件限制的特化版本
如對于下面的模板類
template<class T1, class T2>
class Data
{
public:Data(){cout << "Data<T1, T2>" << endl;}private:T1 _d1;T2 _d2;
};
偏特化有以下兩種表現方式:
a.? 將模板參數類表中的一部分參數特化
template<class T1>
class Data<T1, int>
{
public:Data(){cout << "Data<T1, int>" << endl;}private:T1 _d1;int _d2;
};
b.? 參數進一步的限制
偏特化并不僅僅是指特化部分參數,而是針對模板參數進一步的條件限制所設計出來的一個特化版本
// 兩個參數特化為指針類型
template<class T1,class T2>
class Data<T1*, T2*>
{
public:Data(){cout << "Data<T1*, T2*>" << endl;}private:T1 _d1;T2 _d2;
};// 兩個參數特化為引用類型
template<class T1, class T2>
class Data<T1&, T2&>
{
public:Data(const T1& d1, const T2& d2):_d1(d1),_d2(d2){cout << "Data<T1&, T2&>" << endl;}private:const T1& _d1;const T1& _d2;
};int main()
{//Test2();Data<double, int> d1; // 調用特化的int版本Data<int, double> d2; // 調用基礎的模板 Data<int*, int*> d3; // 調用特化的指針版本Data<int&, int&> d4(1, 2); // 調用特化的引用版本return 0;
}
3.模板分離編譯
一個程序(項目)由若干個源文件共同實現,而每個源文件單獨編譯生成目標文件,最后將所有目標文件鏈 接起來形成單一的可執行文件的過程稱為分離編譯模式
模板聲明與定義如果分開在兩個文件寫,會鏈接不上
解決辦法:
1.將聲明和定義放在一個文件里面(推薦)
2.模板定義的位置顯式實例化(不推薦)
4.模板總結
優點:
1. 模板復用了代碼,節省資源,更快的迭代開發,C++的標準模板庫(STL)因此而產生
2. 增強了代碼的靈活性
缺點
1. 模板會導致代碼膨脹問題,也會導致編譯時間變長
2. 出現模板編譯錯誤時,錯誤信息非常凌亂,不易定位錯誤
?新手寫博客,有不對的位置希望大佬們能夠指出,也謝謝大家能看到這里,讓我們一起學習進步吧!!?