1. 程式人生 > >C++筆記 第五十九課 類模板深度剖析---狄泰學院

C++筆記 第五十九課 類模板深度剖析---狄泰學院

如果在閱讀過程中發現有錯誤,望評論指正,希望大家一起學習,一起進步。
學習C++編譯環境:Linux

第五十九課 類模板深度剖析

1.多引數類模板

類模板可以定義任意多個不同的型別引數
在這裡插入圖片描述
類模板可以被特化
指定類模板的特定實現
部分型別引數必須顯示指定
根據型別引數分開實現類模板
在這裡插入圖片描述
類模板的特化型別
部分特化-用特定規則約數型別引數
完全特化-完全顯示指定型別引數
在這裡插入圖片描述

59-1 類模板的特化—重點程式

#include<iostream>
#include<string>
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);    
    t2.add(5,5);
    t2.print();
    t3.add(NULL, NULL);
    Test<int*, double*> t4;
    int a = 1;
    double b = 0.1;
    t4.add(&a, &b);
    return 0;
}
執行結果
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
******

類模板特化注意事項
特化只是模板的分開實現
本質上是用一類模板
特化類模板的使用方式是統一的
必須顯示指定每一個型別引數

2.問題

類模板特化與重定義有區別嗎?函式模板可以特化嗎?有區別,可以特化。

3.特化的深度分析

重定義和特化的不同
重定義
一個類模板和一個新類(或者兩個類模板)
使用的時候需要考慮如何選擇的問題
特化
以統一的方式使用類模板和特化類
編譯器自動優先選擇特化類
函式模板只支援型別引數完全特化,不支援部分特化

59-2 特化的深入理解

#include<iostream>
#include<string>
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
< >
class Test <void* , void*>
{
public:
    void add(void* a, void* b)
    {
	cout << "void  add(void* a, void* b)" << endl;
	cout << "Error to add void* param..." << endl;
    }
};
*/
class Test_Void //重定義
{
public:
    void add(void* a, void* b)
    {
	cout << "void  add(void* a, void* b)" << endl;
	cout << "Error to add void* param..." << endl;
    }
};
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.00000000001;
    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.00000000001;
    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<double>(0.001, 0.001) << endl;和cout << Equal<>(0.001, 0.001) << endl;兩種寫法是等價的
    //cout << Equal(0.001, 0.001) << endl;//呼叫全域性過載函式,因為編譯器優先選擇
    cout << Equal<>(0.001, 0.001) << endl;//告訴編譯器放棄過載函式,直接使用模板完全特化
    return 0;
}
執行結果
bool Equal(T a, T b) 
1
bool Equal<double>(double a, double b)//函式模板的完全特化實現 
1

4.工程中的建議

當需要過載函式模板時,優先考慮使用模板特化;當模板特化無法滿足需求,再使用函式過載!
小結
類模板可以定義任意多個不同的型別引數
類模板可以被部分特化和完全特化
特化的本質是模板的分開實現
函式模板只支援完全特化
工程中使用模板特化代替類(函式)重定義