C++中有幾種交換變量的方法?
交換變量的方法——定義宏代碼塊 vs 定義函數:ios
C++中有沒有解決方案集合兩種方法的優勢?編程
泛型編程的概念——不考慮具體數據類型的編程方式
數組
函數模板:數據結構
函數模板的語法規則:ide
函數模板的使用:函數
示例——使用函數模板:spa
#include <iostream> using namespace std; template < typename T > void Swap(T& a, T& b) { T c = a; a = b; b = c; } template < typename T > void Sort(T a[], int len) { for(int i=0; i<len; i++) { for(int j=i; j<len; j++) { if( a[i] > a[j] ) { Swap(a[i], a[j]); } } } } template < typename T > void Println(T a[], int len) { for(int i=0; i<len; i++) { cout << a[i] << ", "; } cout << endl; } int main() { int a[5] = {5, 3, 2, 4, 1}; Println(a, 5); Sort(a, 5); Println(a, 5); string s[5] = {"Java", "C++", "Pascal", "Ruby", "Basic"}; Println(s, 5); Sort(s, 5); Println(s, 5); return 0; }
運行結果爲:指針
[root@bogon Desktop]# g++ test.cpp [root@bogon Desktop]# ./a.out 5, 3, 2, 4, 1, 1, 2, 3, 4, 5, Java, C++, Pascal, Ruby, Basic, Basic, C++, Java, Pascal, Ruby,
函數模板深刻理解:code
注意事項:對象
示例——編譯器從函數模板經過具體類型產生不一樣的函數:
#include <iostream> using namespace std; template < typename T > void Swap(T& a, T& b) { T c = a; a = b; b = c; } typedef void(FuncI)(int&, int&); typedef void(FuncD)(double&, double&); int main() { FuncI* pi = Swap; // 編譯器自動推導 T 爲 int FuncD* pd = Swap; // 編譯器自動推導 T 爲 double cout << "pi = " << reinterpret_cast<void*>(pi) << endl; cout << "pd = " << reinterpret_cast<void*>(pd) << endl; return 0; }
運行結果爲:
[root@bogon Desktop]# g++ test.cpp [root@bogon Desktop]# ./a.out pi = 0x40091e pd = 0x40094a
能夠看到,編譯器經過函數模板產生了兩個地址不一樣的實實在在的函數!
多參數函數模板——函數模板能夠定義任意多個不一樣的類型參數:
對於多參數函數模板:
示例——多參數函數模板:
#include <iostream> using namespace std; template < typename T1, typename T2, typename T3 > T1 Add(T2 a, T3 b) { return static_cast<T1>(a + b); } int main() { // T1 = int, T2 = double, T3 = double int r1 = Add<int>(0.5, 0.8); // T1 = double, T2 = float, T3 = double double r2 = Add<double, float>(0.5, 0.8); // T1 = float, T2 = float, T3 = float float r3 = Add<float, float, float>(0.5, 0.8); cout << "r1 = " << r1 << endl; // r1 = 1 cout << "r2 = " << r2 << endl; // r2 = 1.3 cout << "r3 = " << r3 << endl; // r3 = 1.3 return 0; }
運行結果爲:
[root@bogon Desktop]# g++ test.cpp [root@bogon Desktop]# ./a.out r1 = 1 r2 = 1.3 r3 = 1.3
當函數重載趕上函數模板會發生什麼?
函數模板能夠像普通函數同樣被重載:
示例——重載函數模板:
#include <iostream> using namespace std; template < typename T > T Max(T a, T b) { cout << "T Max(T a, T b)" << endl; return a > b ? a : b; } int Max(int a, int b) { cout << "int Max(int a, int b)" << endl; return a > b ? a : b; } template < typename T > T Max(T a, T b, T c) { cout << "T Max(T a, T b, T c)" << endl; return Max(Max(a, b), c); } int main() { int a = 1; int b = 2; cout << Max(a, b) << endl; // 普通函數 Max(int, int) cout << Max<>(a, b) << endl; // 函數模板 Max<int>(int, int) cout << endl; cout << Max(3.0, 4.0) << endl; // 函數模板 Max<double>(double, double) cout << Max(5.0, 6.0, 7.0) << endl; // 函數模板 Max<double>(double, double, double) cout << endl; cout << Max('a', 100) << endl; // 普通函數 Max(int, int) return 0; }
運行結果爲:
[root@bogon Desktop]# g++ test.cpp [root@bogon Desktop]# ./a.out int Max(int a, int b) 2 T Max(T a, T b) 2 T Max(T a, T b) 4 T Max(T a, T b, T c) T Max(T a, T b) T Max(T a, T b) 7 int Max(int a, int b) 100
在C++中是否可以將泛型的思想應用於類?
類模板:
C++中將模板的思想應用於類,使得類的實現不關注數據元素的具體類型,而只關注類所須要實現的功能。
C++中的類模板:
類模板的應用:
示例——類模板:
#include <iostream> using namespace std; template < typename T > class Operator { public: T add(T a, T b) { return a + b; } T minus(T a, T b) { return a - b; } T multiply(T a, T b) { return a * b; } T divide(T a, T b) { return a / b; } }; string operator-(string& l, string& r) { return "Minus"; } int main() { Operator<int> op1; cout << op1.add(1, 2) << endl; Operator<string> op2; cout << op2.add("Hello", "World") << endl; cout << op2.minus("Hello", "World") << endl; return 0; }
運行結果爲:
[root@bogon Desktop]# g++ test.cpp [root@bogon Desktop]# ./a.out 3 HelloWorld Minus
類模板的工程應用:
示例——模板類的工程應用:
// Operator.h #ifndef _OPERATOR_H_ #define _OPERATOR_H_ template < typename T > class Operator { public: T add(T a, T b); T minus(T a, T b); T multiply(T a, T b); T divide(T a, T b); }; template < typename T > T Operator<T>::add(T a, T b) { return a + b; } template < typename T > T Operator<T>::minus(T a, T b) { return a - b; } template < typename T > T Operator<T>::multiply(T a, T b) { return a * b; } template < typename T > T Operator<T>::divide(T a, T b) { return a / b; } #endif
// test.cpp #include <iostream> #include "Operator.h" using namespace std; int main() { Operator<int> op1; cout << op1.add(1, 2) << endl; cout << op1.multiply(4, 5) << endl; cout << op1.minus(5, 6) << endl; cout << op1.divide(10, 5) << endl; return 0; }
運行結果爲:
[root@bogon Desktop]# g++ test.cpp [root@bogon Desktop]# ./a.out 3 20 -1 2
類模板能夠定義任意多個不一樣的類型參數:
類模板能夠被特化:
類模板的特化類型:
示例——類模板的特化:
#include <iostream> using namespace std; template < typename T1, typename T2 > class Test { public: void add(T1 a, T2 b) { cout << "void add(T1 a, T2 b)" << endl; cout << a + b << endl; } }; template < typename T1, typename T2 > class Test < T1*, T2* > // 關於指針的特化實現 { public: void add(T1* a, T2* b) { cout << "void add(T1* a, T2* b)" << endl; cout << *a + *b << endl; } }; template < typename T > class Test < T, T > // 當 Test 類模板的兩個類型參數徹底相同時,使用這個實現 { public: void add(T a, T b) { cout << "void add(T a, T b)" << endl; cout << a + b << endl; } void print() { cout << "class Test < T, T >" << endl; } }; template < > class Test < void*, void* > // 當 T1 == void* 而且 T2 == void* 時 { public: void add(void* a, void* b) { cout << "void add(void* a, void* b)" << endl; cout << "Error to add void* param..." << endl; } }; int main() { Test<int, float> t1; Test<long, long> t2; Test<void*, void*> t3; t1.add(1, 2.5); cout << endl; t2.add(5, 5); t2.print(); cout << endl; t3.add(NULL, NULL); cout << endl; Test<int*, double*> t4; int a = 1; double b = 0.1; t4.add(&a, &b); return 0; }
運行結果爲:
[root@bogon Desktop]# g++ test.cpp [root@bogon Desktop]# ./a.out void add(T1 a, T2 b) 3.5 void add(T a, T b) 10 class Test < T, T > void add(void* a, void* b) Error to add void* param... void add(T1* a, T2* b) 1.1
類模板特化注意事項:
類模板特化與重定義有區別嗎?函數模板能夠被特化嗎?
重定義和特化的不一樣:
函數模板只支持類型參數徹底特化:
示例——函數模板徹底特化與函數重載:
#include <iostream> using namespace std; template < typename T > bool Equal(T a, T b) { cout << "bool Equal(T a, T b)" << endl; return a == b; } template < > bool Equal<double>(double a, double b) { const double delta = 0.00000000000001; double r = a - b; cout << "bool Equal<double>(double a, double b)" << endl; return (-delta < r) && (r < delta); } bool Equal(double a, double b) { const double delta = 0.00000000000001; double r = a - b; cout << "bool Equal(double a, double b)" << endl; return (-delta < r) && (r < delta); } int main() { cout << Equal( 1, 1 ) << endl; cout << Equal( 0.001, 0.001 ) << endl; cout << Equal<>( 0.001, 0.001 ) << endl; return 0; }
運行結果爲:
[root@bogon Desktop]# g++ test.cpp [root@bogon Desktop]# ./a.out bool Equal(T a, T b) 1 bool Equal(double a, double b) 1 bool Equal<double>(double a, double b) 1
工程中的建議:
當須要重載函數模板時,優先考慮使用模板特化;當模板特化沒法知足需求,再使用函數重載!