C++面向物件入門(三十六)模板概念和初步認識函式模板
阿新 • • 發佈:2020-09-02
強型別語言的特點:
1 程式可靠性較高:在編譯執行前必須經過嚴格的型別檢查, 達到在執行前就檢查出型別不相容的錯誤.
2 靈活性較低: 對於默寫處理邏輯完全一樣, 但是資料型別不同的變數的操作必須按照型別分別定義. 解決強型別的嚴格性和靈活性的衝突的途徑:
1 使用巨集函式: 方便, 但是可能不帶來其他安全問題, C++不提倡
2 為每個資料型別過載相同的函式, 麻煩
3 放鬆型別檢查, 在編譯時忽略, 推遲到執行期間作型別匹配檢查, 可能在程式執行期間出現型別不相容的情況
4 將資料型別作為引數(類屬機制Genericity) C++通過模板機制實現類屬機制 模板機制: 一種引數化多型性的工具, 為邏輯功能相同而型別不同的程式提供程式碼共享機制 C++中的模板機制, 模板並非實實在在的函式或類, 僅僅是函式或類的描述, 模板運算物件的型別不是實際的資料型別,
而是一種引數化的型別(類屬型別), 根據使用類似型別的構件, 又分為:
1 類模板:對一批僅有資料型別不同類的抽象, 只需為這一批類組成的整個類家族建立一個類模板, 然後給出一套程式程式碼, 就
可以用來生成多種具體類, 即模板類. 由於類模板需要一種或多種型別引數, 因此又被稱為引數化類
優點:提高程式設計效率, 提高程式碼可重用性 類和類模板: 類是對一族具有公共性質的物件的抽象, 而類模板則是對一組具有公共性質的類的抽象, 類模板是更高層次的抽象化 如何定義類模板?
template<模板引數表>
class <類模板名>
{
<類成員宣告>
} 使用類模板的注意事項:
1 模板引數表包含一個多個用逗號分開的型別, 引數項可以包含基本資料型別, 也可以包含類型別, 如果是類型別, 必須加字首class
或typename
2 類模板的成員函式和過載運算子必須為模板函式, 可以在類內定義, 定義方式和定義成員函式一致, 也可以放在類模板外部, 此時
定義方式如下
template<模板引數名>
<返回值型別> <類模板名>< <型別名錶> >::<成員函式名>(<引數表>)
{
<函式體>
}
3 與函式模板不同的是, 函式模板的例項化是由編譯系統在處理函式呼叫時自動完成, 而類模板的例項化必須在程式中顯式地指定
在類模板例項化為模板類時(使用類模板經例項化而成的具體類), 類模板中的成員函式自動例項化為模板函式
如何定義模板類物件
<類模板名>< <型別實參表> > <物件名>(<實參表>) 對於上述定義方式欄位的解釋:
類名名錶: 類模板定義中的模板引數表中的引數名 如何例項化類模板?
語法:
<類模板名> < <型別實參表> > 2 函式模板: 可以一次定義出具有共性(除型別引數外, 其餘全部相同)的一組函式, 同時也可以處理多種不同型別資料的函式
優點:增強了函式設計的通用性 如何定義函式模板: 先實現函式模板, 然後例項化構造出相應的模板函式進行呼叫執行 定義函式模板的語法:
template<模板引數表>
<返回值型別> <函式名>(<引數表>)
{
<函式體>
} 模板引數表的定義語法;
typename(class) 模板引數名,... 使用函式模板的注意事項:
1 模板引數可以在函式的任何地方使用
2 函式的引數表可以使用模板引數, 也可以使用一般型別引數(基本型別, 使用者自定義型別), 但引數表至少又一個形參的
型別必須使用模板引數表的模板引數,
3 模板引數表中的每一個模板引數都必須在引數表中得到使用
4 函式模板的宣告和定義必須是全域性作用域, 模板不能被宣告為類的成員函式
5 編譯器不會為沒有用到的任何型別生成相應的模板函式
6 一個型別無論使用多少次函式模板, 都只為該型別生成一個模板函式 函式模板的程式碼示例:
1 程式可靠性較高:在編譯執行前必須經過嚴格的型別檢查, 達到在執行前就檢查出型別不相容的錯誤.
2 靈活性較低: 對於默寫處理邏輯完全一樣, 但是資料型別不同的變數的操作必須按照型別分別定義. 解決強型別的嚴格性和靈活性的衝突的途徑:
1 使用巨集函式: 方便, 但是可能不帶來其他安全問題, C++不提倡
2 為每個資料型別過載相同的函式, 麻煩
3 放鬆型別檢查, 在編譯時忽略, 推遲到執行期間作型別匹配檢查, 可能在程式執行期間出現型別不相容的情況
4 將資料型別作為引數(類屬機制Genericity) C++通過模板機制實現類屬機制 模板機制: 一種引數化多型性的工具, 為邏輯功能相同而型別不同的程式提供程式碼共享機制 C++中的模板機制, 模板並非實實在在的函式或類, 僅僅是函式或類的描述, 模板運算物件的型別不是實際的資料型別,
1 類模板:對一批僅有資料型別不同類的抽象, 只需為這一批類組成的整個類家族建立一個類模板, 然後給出一套程式程式碼, 就
可以用來生成多種具體類, 即模板類. 由於類模板需要一種或多種型別引數, 因此又被稱為引數化類
優點:提高程式設計效率, 提高程式碼可重用性 類和類模板: 類是對一族具有公共性質的物件的抽象, 而類模板則是對一組具有公共性質的類的抽象, 類模板是更高層次的抽象化 如何定義類模板?
template<模板引數表>
class <類模板名>
{
<類成員宣告>
} 使用類模板的注意事項:
或typename
2 類模板的成員函式和過載運算子必須為模板函式, 可以在類內定義, 定義方式和定義成員函式一致, 也可以放在類模板外部, 此時
定義方式如下
template<模板引數名>
<返回值型別> <類模板名>< <型別名錶> >::<成員函式名>(<引數表>)
{
<函式體>
}
3 與函式模板不同的是, 函式模板的例項化是由編譯系統在處理函式呼叫時自動完成, 而類模板的例項化必須在程式中顯式地指定
<類模板名>< <型別實參表> > <物件名>(<實參表>) 對於上述定義方式欄位的解釋:
類名名錶: 類模板定義中的模板引數表中的引數名 如何例項化類模板?
語法:
<類模板名> < <型別實參表> > 2 函式模板: 可以一次定義出具有共性(除型別引數外, 其餘全部相同)的一組函式, 同時也可以處理多種不同型別資料的函式
優點:增強了函式設計的通用性 如何定義函式模板: 先實現函式模板, 然後例項化構造出相應的模板函式進行呼叫執行 定義函式模板的語法:
template<模板引數表>
<返回值型別> <函式名>(<引數表>)
{
<函式體>
} 模板引數表的定義語法;
typename(class) 模板引數名,... 使用函式模板的注意事項:
1 模板引數可以在函式的任何地方使用
2 函式的引數表可以使用模板引數, 也可以使用一般型別引數(基本型別, 使用者自定義型別), 但引數表至少又一個形參的
型別必須使用模板引數表的模板引數,
3 模板引數表中的每一個模板引數都必須在引數表中得到使用
4 函式模板的宣告和定義必須是全域性作用域, 模板不能被宣告為類的成員函式
5 編譯器不會為沒有用到的任何型別生成相應的模板函式
6 一個型別無論使用多少次函式模板, 都只為該型別生成一個模板函式 函式模板的程式碼示例:
#include <iostream> using namespace std; /* 強型別語言的特點: 1 程式可靠性較高:在編譯執行前必須經過嚴格的型別檢查, 達到在執行前就檢查出型別不相容的錯誤. 2 靈活性較低: 對於默寫處理邏輯完全一樣, 但是資料型別不同的變數的操作必須按照型別分別定義. 解決強型別的嚴格性和靈活性的衝突的途徑: 1 使用巨集函式: 方便, 但是可能不帶來其他安全問題, C++不提倡 2 為每個資料型別過載相同的函式, 麻煩 3 放鬆型別檢查, 在編譯時忽略, 推遲到執行期間作型別匹配檢查, 可能在程式執行期間出現型別不相容的情況 4 將資料型別作為引數(類屬機制Genericity) C++通過模板機制實現類屬機制 模板機制: 一種引數化多型性的工具, 為邏輯功能相同而型別不同的程式提供程式碼共享機制 C++中的模板機制, 模板並非實實在在的函式或類, 僅僅是函式或類的描述, 模板運算物件的型別不是實際的資料型別, 而是一種引數化的型別(類屬型別), 根據使用類似型別的構件, 又分為: 1 類模板:對一批僅有資料型別不同類的抽象, 只需為這一批類組成的整個類家族建立一個類模板, 然後給出一套程式程式碼, 就 可以用來生成多種具體類, 即模板類. 由於類模板需要一種或多種型別引數, 因此又被稱為引數化類 優點:提高程式設計效率, 提高程式碼可重用性 類和類模板: 類是對一族具有公共性質的物件的抽象, 而類模板則是對一組具有公共性質的類的抽象, 類模板是更高層次的抽象化 如何定義類模板? template<模板引數表> class <類模板名> { <類成員宣告> } 使用類模板的注意事項: 1 模板引數表包含一個多個用逗號分開的型別, 引數項可以包含基本資料型別, 也可以包含類型別, 如果是類型別, 必須加字首class 或typename 2 類模板的成員函式和過載運算子必須為模板函式, 可以在類內定義, 定義方式和定義成員函式一致, 也可以放在類模板外部, 此時 定義方式如下 template<模板引數名> <返回值型別> <類模板名>< <型別名錶> >::<成員函式名>(<引數表>) { <函式體> } 3 與函式模板不同的是, 函式模板的例項化是由編譯系統在處理函式呼叫時自動完成, 而類模板的例項化必須在程式中顯式地指定 在類模板例項化為模板類時(使用類模板經例項化而成的具體類), 類模板中的成員函式自動例項化為模板函式 如何定義模板類物件 <類模板名>< <型別實參表> > <物件名>(<實參表>) 對於上述定義方式欄位的解釋: 類名名錶: 類模板定義中的模板引數表中的引數名 如何例項化類模板? 語法: <類模板名> < <型別實參表> > 2 函式模板: 可以一次定義出具有共性(除型別引數外, 其餘全部相同)的一組函式, 同時也可以處理多種不同型別資料的函式 優點:增強了函式設計的通用性 如何定義函式模板: 先實現函式模板, 然後例項化構造出相應的模板函式進行呼叫執行 定義函式模板的語法: template<模板引數表> <返回值型別> <函式名>(<引數表>) { <函式體> } 模板引數表的定義語法; typename(class) 模板引數名,... 使用函式模板的注意事項: 1 模板引數可以在函式的任何地方使用 2 函式的引數表可以使用模板引數, 也可以使用一般型別引數(基本型別, 使用者自定義型別), 但引數表至少又一個形參的 型別必須使用模板引數表的模板引數, 3 模板引數表中的每一個模板引數都必須在引數表中得到使用 4 函式模板的宣告和定義必須是全域性作用域, 模板不能被宣告為類的成員函式 5 編譯器不會為沒有用到的任何型別生成相應的模板函式 6 一個型別無論使用多少次函式模板, 都只為該型別生成一個模板函式 */ //定義函式模板 template<typename T> T min(T a, T b) { return a < b ? a : b; } //嘗試在函式模板引數表中不使用模板引數, 僅在返回值型別和函式內使用 template<typename E> E func1(int i, double d) { cout << i << " " << d << endl; E e; return e; } //沒有報錯 //但在使用函式模板時會報錯 //嘗試在函式模板引數表中只使用部分模板引數 template<typename E, typename V> E func2(E e) { cout << e << endl; } //沒有報錯 //但在使用函式模板時會報錯 class A53 { private: int x; int y; public: A53(); A53(int, int); bool operator<(const A53 &a); friend ostream &operator<<(ostream &cout, const A53& a); }; int main() { double d1, d2; d1 = 3.7; d2 = 5.3; cout << d1 << " and " << d2 << " min is " << min(d1, d2) << endl; int i1, i2; i1 = 12; i2 = 34; cout << i1 << " and " << i2 << " min is " << min(i1, i2) << endl; char c1, c2; c1 = 'a'; c2 = 'A'; cout << c1 << " and " << c2 << " min is " << min(c1, c2) << endl; A53 a1(2, 1); A53 a2(1, 3); A53 a3(2, 2); cout << a1 << " and " << a2 << " min is " << min(a1, a2) << "}" << endl; cout << a1 << " and " << a3 << " min is " << min(a1, a3) << "}" << endl; cout << a2 << " and " << a3 << " min is " << min(a2, a3) << "}" << endl; A53 a4; //A53 a = func2(a4); //沒有與引數型別匹配的函式模板'func2'例項 // 引數型別為(A53) //func1(1, 2.5); //沒有與引數型別匹配的函式模板'func2'例項 // 引數型別為(int, double) system("pause"); } A53::A53() { cout << "A53" << endl; } A53::A53(int x, int y):x(x),y(y) {} bool A53::operator<(const A53 & a) { if (x == a.x) { return y < a.y; } return x < a.x; } ostream & operator<<(ostream & cout, const A53 & a) { cout << "A53{x:" << a.x << ", y:" << a.y; return cout; }