C++學習筆記 第59課類别範本深度刨析

脆香米送給你發表於2020-10-30

多引數類别範本

類别範本可以定義任意多個不同的型別引數,其中int對應t1,float對應t2
在這裡插入圖片描述
類别範本可以被特化

  • 指定類别範本的特定實現
  • 部分引數型別必須顯示指定
  • 根據型別引數分開實現類别範本
    在這裡插入圖片描述
    類别範本的特化型別
    部分特化-用特定的規則約束型別引數
    完全特化-完全顯示指定型別引數
    在這裡插入圖片描述
    59-1.cpp
#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類别範本的兩個型別引數完全相同時,呼叫這個模板,部分特化
{
public:
	void add(T a, T b)
	{
		cout << "add(T a, T b)" << endl;
		cout << a + b << endl;
	}
};


template//完全特化,不需要型別宣告,如果T1,T2引數都為Void*的時候使用此實現
<>
class Test<void*, void*>
{
public:
	void add(void* a, void* b)
	{
		cout << "add(void* a, void* b)" << endl;
		cout <<"error on param"<< endl;
	}
};

template
<typename T1, typename T2>
class Test<T1*, T2*>
{
public:
	void add(T1* a, T2* b)
	{
		cout << "add(T1* a, T2* b)" << endl;
		cout << *a + *b << endl;
	}
};

int main()
{
	Test<int, float> t1;
    Test<int, int> t2;
	Test<void*, void*>t3;
	Test<int*, float*>t4;
	int a = 10;
	float b = 10.5;

	t1.add(1,2);
	t2.add(1,2);
	t3.add(NULL, NULL);
	t4.add(&a, &b);

	return 0;
}

結果:
void add(T1 a, T2 b)
3
add(T a, T b)
3
add(void* a, void* b)
error on param
add(T1* a, T2* b)
20.5

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

2. 問題:

類别範本特化與重定義有什麼區別?函式模板可以特化嗎?有區別,有區別

3.特化的深度分析

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

59-2.cpp 特化的深入理解

template
<typename T>    //函式模板定義
bool Equal(T a,T b)
{
	return a == b;
}

template //函式模板完全特化
<>
bool Equal<void*>(void *a,void* b)
{
	return a == b
}

工程中的建議:當需要過載函式模板時,優先考慮模板特化,當模板無法滿足時,再使用函式過載(兩個都存在時,編譯器預設選擇全域性的函式過載)

#include <iostream>
using namespace std;


//函式模板
template
<typename T>
bool equal(T a, T b)
{
    const double delta = 1e-10;
    double r = a - b;

    cout << "bool Equal(T a, T b) " << endl;
    return (-delta < r) && (r < delta);
}

//函式過載
bool equal(double a, double b)
{
    const double delta = 1e-10;
    double r = a - b;

    cout << "bool equal(double a,double b)" << endl;
    return (-delta < r) && (r < delta);
}

//函式模板完全特化
template
<>
bool equal<double>(double a, double b)
{
    cout << "bool equal<double>(double a, double b)" << endl;

    return a == b;
}


int main()
{
    double a = 12.2222;
    double b = 12.2222222;

    cout << equal(a, b) << endl;//兩個的存在時,輸出bool equal(double a, double b)
                                //全域性過載不存在時,呼叫完全特化的函式模板
    cout << equal<>(a, b) << endl;//呼叫函式特化
    return 0;
}

小結

1.類别範本可以定義任意多個不同型別的引數
2.類别範本被部分特化和完全特化
3.特化的本質是模板的分開實現
4.函式模板只支援完全特化
5.工程中使用模板特化代替類(函式重定義)

相關文章