1、類模板的泛指類型可以定義多個 template <typename T1, typename T2> class Test { public: void add(T1 a, T2, b); }; 使用時: Test<int, float> t1; //T1的泛指類型就是int, T2的泛指類型就是float。 2、類模板的特化類型 (1)意思就是如果定義了一個類模板,這個類模板的參數(shù)有多個,但是如果當使用這個類模板的時候,我們傳遞參數(shù)時,參數(shù)的類型是一樣的話,編譯器就會將類模板特化成一個參數(shù)的類模板。 (2)類模板的特化分為:部分特化,和完全特化。 部分特化:用特定規(guī)則約束類型參數(shù),部分類型參數(shù)必須顯示指定,根據(jù)類型參數(shù)分開實現(xiàn)類模板 如: template 特化后 template < typename T1, typname T2 > < typename T > class Test class Test <T, T> //部分特化的約束條件 { { }; }; 當類型參數(shù)不同的時候,會選擇用左邊的那個類模板,當類型參數(shù)相同的時候。class Test< T, T>就是約束條件 完全特化:完全顯示指定類型參數(shù) 如: template 特化后 template < typename T1, typname T2 > < > //完全特化時,不需要聲明泛指類型 class Test class Test <int, int> //這個就是完全特化 { { }; }; 當使用類模板的時候,并且指定了所有的類型參數(shù)全都是一樣的,比如int的時候,編譯器就會將左邊的類模板特化成右邊的類模板,此時該類模板中就沒有泛指類型了。 當類型參數(shù)不同的時候,就會使用左邊的類模板。 (3)根據(jù)實驗的例子,類模板的特化就是程序中有了一個左邊的類模板的時候(這個類模板的有兩個泛指類型),但是同時程序中我們又定義了一個同名的類模板,但是這個類模板的兩個泛指類型都是一樣的。這個時候,當我們在程序中使用這個類模板的時候,如果參數(shù)類型是不一樣的,編譯器就會使用左邊的那個,如果參數(shù)類型是一樣的時候,編譯器就會使用右面的那個。編譯器會認為右邊的那個類模板,是左邊的類模板的一種特化,編譯器不會認為左邊的類模板是一個新的類模板,只是一個左邊類模板的一個特化,所以編譯能夠通過。 總結(jié):將一個類模板,根據(jù)不同的類型參數(shù)情況進行分開實現(xiàn)這個類模板,其實就是一個類模板的特化過程。 例: #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 T> class Test < T, T > //這個地方加上了約束條件,雖然這個類模板跟上面的那個類模板同名,編譯器不會認為這個類模板是一個新的類模板,而是上面類模板的一個特化形式, { //當我們使用Test類模板的時候,如果指定的參數(shù)類型不同的話,編譯器就會使用上面的那個類模板實現(xiàn),如果指定參數(shù)類型相同的話,編譯器就會使用這個類模板的實現(xiàn) public: void add(T a, T b) { cout << "void add(T a, T b)" << endl; cout << a + b << endl; } void print(void) //即使多出來了個print成員函數(shù),編譯也是通過的,所以是支持這種特化方式的 { cout << "class Test < T, T > " << endl; } }; /******************************************************完全特化**********************************************************/ template < > //進行類模板的完全特化時,不用進行泛指類型的聲明 class Test <void *, void *> //當使用Test類模板時,參數(shù)類型都為void *時,就會使用這個實現(xiàn)。 { public: void add(void * a, void * b) { cout << "void add(void * a, void * b)" << endl; cout << "Error run not to add because type is void *..." << endl; } }; /*****************************************將Test類模板特化出一個兩個參數(shù)分別是指針的情況**********************************************/ 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; } }; int main(void) { int a = 1; double b = 1.0; Test<int, float> t1; //使用的就是沒有特化的Test類模板 Test<long, long> t2; //使用的就是特化后的Test類模板 Test<void *, void *> t3; Test<int *, double *> t4; t1.add(2, 2.5); t2.add(10, 10); t2.print(); t3.add(&a, &b); t4.add(&a, &b); return 0; } 3、繼續(xù)理解類模板的特化 (1)類模板的特化的就是根據(jù)需要,將一個類模板進行分開來實現(xiàn)。特化只是模板的分開實現(xiàn),本質(zhì)上還是同一個類模板。特化類模板的使用方式是統(tǒng)一的,就是必須顯示的指定每一個類型參數(shù)。 (2)問題:類模板特化與重定義有區(qū)別嗎? 答:有區(qū)別,重定義和特化不同。在本質(zhì)上,如果將一個類模板進行重定義,那么要么就是實現(xiàn)了一個新的類,要么就是最后會出現(xiàn)兩個類模板。本質(zhì)上不同。使用的時候不能進行統(tǒng)一使用, 在使用時我們要考慮選擇哪個。 特化的本質(zhì)是,只實現(xiàn)同一個類模板,只不過這個類模板是分開來實現(xiàn)的,這就是本質(zhì)上的不同。在使用時是用統(tǒng)一的方式進行使用類模板和特化類,因為本質(zhì)上都是實現(xiàn)了一個類模板,使用時 編譯器會根據(jù)不同的參數(shù)類型來選擇去使用那個類模板還是特化類。所以類模板的特化就是將一個類模板進行分開來實現(xiàn),這句話是非常重要的。 (3)問題:函數(shù)模板可以特化嗎? 答:函數(shù)模板只支持類型參數(shù)的完全特化,不支持部分特化,也就是在函數(shù)名的后面顯示的指定出具體的參數(shù)類型。 如:函數(shù)模板的完全特化 template < typename T > bool Equal(T a, T b) //函數(shù)模板的定義 { return a == b; } template < > bool Equal<void *>(void *, void *) //函數(shù)模板的完全特化 { return a == b; } (4)工程中的建議:當需要重載函數(shù)模板的時候,我們要優(yōu)先考慮使用模板特化的方式去分開實現(xiàn)一個函數(shù)模板,而是不用重載函數(shù)模板的方式去新的實現(xiàn)了一個函數(shù),當模板特化無法滿足要 求的時候,在使用函數(shù)重載。 工程中使用模板特化來代替類(函數(shù))重定義。 例:類模板的部分特化、完全特化,函數(shù)模板的完全特化。優(yōu)先考慮使用特化的方式當需要將模板進行重定義添加功能時。 #include <iostream> #include <string> using namespace std; /* * 特化的方式實現(xiàn)一個類模板,本質(zhì)就是分開實現(xiàn)類模板 * */ template <typename T1, typename T2> class Why { public: void print(T1 a, T2 b) { cout << "void print(T1 a, T2 b)" << endl; cout << a << " " << b << endl; } }; template <typename T> class Why<T, T> //為類模板的部分特化 { public: void print(T a, T b) { cout << "void print(T a, T b)" << endl; cout << a << " " << b << endl; } }; template < > class Why<int, int> //為類模板的完全特化 { public: void print(int a, int b) { cout << "void print(int a, int b)" << endl; cout << a << " " << b << endl; } }; /* * 函數(shù)模板的特化只支持完全特化 * 實現(xiàn)一個函數(shù)模板,并且完全特化,也就是分開實現(xiàn)一個函數(shù)模板,這樣叫做特化。 */ template <typename T> bool Equal(T a, T b) { return a == b; } template < > //函數(shù)模板的完全特化,之所以要特化這個函數(shù)模板是因為,浮點數(shù)的比較不單純的只用==來比較。 bool Equal<double>(double a, double b) { const double delta = 0.00000000001; double r = a - b; cout << "bool Equal<double>(double a, double b)" << endl; return ((-delta < r) && (r < delta)); } /* * 重載Equal函數(shù)的方式來達到比較浮點數(shù)的方法,但這種方式是不優(yōu)先考慮的,因為這種方式,在使用的時候要考慮如何選擇,要優(yōu)先考慮使用特化的方式。 * 能使用特化的方式時,就不考慮使用這種函數(shù)重載的方式,不論對于類模板還是函數(shù)模板都是這樣的,優(yōu)先考慮使用特化的方式來分開實現(xiàn),因為這樣都是為了實現(xiàn)一個類模板或函數(shù)模板。 */ bool Equal(double a, double b) { const double delta = 0.00000000001; double r = a - b; cout << "bool Equal(double a, double b)" << endl; return ((-delta < r) && (r < delta)); } int main(void) { double a = 0.0, b = 0.0; Why<int, double> w1; Why<string, string> w2; Why<int, int>w3; w2.print("why", "fangqingqing"); w1.print(1, 2.2); w3.print(100,100); cout << "Please input two double number..." << endl; cin >> a >> b; cout << Equal<double>(a, b) << endl; cin >> a >> b; cout << Equal(a, b) << endl; return 0; }
分享文章:c++類模板深度剖析
分享路徑:http://www.chinadenli.net/article48/gpesep.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供App設(shè)計、定制開發(fā)、網(wǎng)站設(shè)計公司、網(wǎng)站策劃、微信小程序、
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)