成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

c++類(lèi)模板深度剖析

1、類(lèi)模板的泛指類(lèi)型可以定義多個(gè)

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

使用時(shí): Test<int, float> t1;	//T1的泛指類(lèi)型就是int, T2的泛指類(lèi)型就是float。

2、類(lèi)模板的特化類(lèi)型

(1)意思就是如果定義了一個(gè)類(lèi)模板,這個(gè)類(lèi)模板的參數(shù)有多個(gè),但是如果當(dāng)使用這個(gè)類(lèi)模板的時(shí)候,我們傳遞參數(shù)時(shí),參數(shù)的類(lèi)型是一樣的話,編譯器就會(huì)將類(lèi)模板特化成一個(gè)參數(shù)的類(lèi)模板。

(2)類(lèi)模板的特化分為:部分特化,和完全特化。

部分特化:用特定規(guī)則約束類(lèi)型參數(shù),部分類(lèi)型參數(shù)必須顯示指定,根據(jù)類(lèi)型參數(shù)分開(kāi)實(shí)現(xiàn)類(lèi)模板
如:

template										特化后				template	
< typename T1, typname T2 >											< typename T >		
class Test															class Test <T, T>	//部分特化的約束條件
{																	{
			
};																	};
當(dāng)類(lèi)型參數(shù)不同的時(shí)候,會(huì)選擇用左邊的那個(gè)類(lèi)模板,當(dāng)類(lèi)型參數(shù)相同的時(shí)候。class Test< T, T>就是約束條件


完全特化:完全顯示指定類(lèi)型參數(shù)
如:
template										特化后				template	
< typename T1, typname T2 >											<  >	//完全特化時(shí),不需要聲明泛指類(lèi)型
class Test															class Test <int, int> //這個(gè)就是完全特化
{																	{
			
};																	};
當(dāng)使用類(lèi)模板的時(shí)候,并且指定了所有的類(lèi)型參數(shù)全都是一樣的,比如int的時(shí)候,編譯器就會(huì)將左邊的類(lèi)模板特化成右邊的類(lèi)模板,此時(shí)該類(lèi)模板中就沒(méi)有泛指類(lèi)型了。
當(dāng)類(lèi)型參數(shù)不同的時(shí)候,就會(huì)使用左邊的類(lèi)模板。

(3)根據(jù)實(shí)驗(yàn)的例子,類(lèi)模板的特化就是程序中有了一個(gè)左邊的類(lèi)模板的時(shí)候(這個(gè)類(lèi)模板的有兩個(gè)泛指類(lèi)型),但是同時(shí)程序中我們又定義了一個(gè)同名的類(lèi)模板,但是這個(gè)類(lèi)模板的兩個(gè)泛指類(lèi)型都是一樣的。這個(gè)時(shí)候,當(dāng)我們?cè)诔绦蛑惺褂眠@個(gè)類(lèi)模板的時(shí)候,如果參數(shù)類(lèi)型是不一樣的,編譯器就會(huì)使用左邊的那個(gè),如果參數(shù)類(lèi)型是一樣的時(shí)候,編譯器就會(huì)使用右面的那個(gè)。編譯器會(huì)認(rèn)為右邊的那個(gè)類(lèi)模板,是左邊的類(lèi)模板的一種特化,編譯器不會(huì)認(rèn)為左邊的類(lèi)模板是一個(gè)新的類(lèi)模板,只是一個(gè)左邊類(lèi)模板的一個(gè)特化,所以編譯能夠通過(guò)。

總結(jié):將一個(gè)類(lèi)模板,根據(jù)不同的類(lèi)型參數(shù)情況進(jìn)行分開(kāi)實(shí)現(xiàn)這個(gè)類(lèi)模板,其實(shí)就是一個(gè)類(lèi)模板的特化過(guò)程。

例:

#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 >		//這個(gè)地方加上了約束條件,雖然這個(gè)類(lèi)模板跟上面的那個(gè)類(lèi)模板同名,編譯器不會(huì)認(rèn)為這個(gè)類(lèi)模板是一個(gè)新的類(lèi)模板,而是上面類(lèi)模板的一個(gè)特化形式,
{				//當(dāng)我們使用Test類(lèi)模板的時(shí)候,如果指定的參數(shù)類(lèi)型不同的話,編譯器就會(huì)使用上面的那個(gè)類(lèi)模板實(shí)現(xiàn),如果指定參數(shù)類(lèi)型相同的話,編譯器就會(huì)使用這個(gè)類(lèi)模板的實(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)		//即使多出來(lái)了個(gè)print成員函數(shù),編譯也是通過(guò)的,所以是支持這種特化方式的
	{
		cout << "class Test < T, T >	" << endl;
	}
};

/******************************************************完全特化**********************************************************/

template
< >		//進(jìn)行類(lèi)模板的完全特化時(shí),不用進(jìn)行泛指類(lèi)型的聲明
class Test <void *, void *>		//當(dāng)使用Test類(lèi)模板時(shí),參數(shù)類(lèi)型都為void *時(shí),就會(huì)使用這個(gè)實(shí)現(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類(lèi)模板特化出一個(gè)兩個(gè)參數(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;	//使用的就是沒(méi)有特化的Test類(lèi)模板
	Test<long, long> t2;	//使用的就是特化后的Test類(lèi)模板
	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ù)理解類(lèi)模板的特化

(1)類(lèi)模板的特化的就是根據(jù)需要,將一個(gè)類(lèi)模板進(jìn)行分開(kāi)來(lái)實(shí)現(xiàn)。特化只是模板的分開(kāi)實(shí)現(xiàn),本質(zhì)上還是同一個(gè)類(lèi)模板。特化類(lèi)模板的使用方式是統(tǒng)一的,就是必須顯示的指定每一個(gè)類(lèi)型參數(shù)。


(2)問(wèn)題:類(lèi)模板特化與重定義有區(qū)別嗎?
答:有區(qū)別,重定義和特化不同。在本質(zhì)上,如果將一個(gè)類(lèi)模板進(jìn)行重定義,那么要么就是實(shí)現(xiàn)了一個(gè)新的類(lèi),要么就是最后會(huì)出現(xiàn)兩個(gè)類(lèi)模板。本質(zhì)上不同。使用的時(shí)候不能進(jìn)行統(tǒng)一使用,
在使用時(shí)我們要考慮選擇哪個(gè)。

特化的本質(zhì)是,只實(shí)現(xiàn)同一個(gè)類(lèi)模板,只不過(guò)這個(gè)類(lèi)模板是分開(kāi)來(lái)實(shí)現(xiàn)的,這就是本質(zhì)上的不同。在使用時(shí)是用統(tǒng)一的方式進(jìn)行使用類(lèi)模板和特化類(lèi),因?yàn)楸举|(zhì)上都是實(shí)現(xiàn)了一個(gè)類(lèi)模板,使用時(shí)
編譯器會(huì)根據(jù)不同的參數(shù)類(lèi)型來(lái)選擇去使用那個(gè)類(lèi)模板還是特化類(lèi)。所以類(lèi)模板的特化就是將一個(gè)類(lèi)模板進(jìn)行分開(kāi)來(lái)實(shí)現(xiàn),這句話是非常重要的。

(3)問(wèn)題:函數(shù)模板可以特化嗎?
答:函數(shù)模板只支持類(lèi)型參數(shù)的完全特化,不支持部分特化,也就是在函數(shù)名的后面顯示的指定出具體的參數(shù)類(lèi)型。

如:函數(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)工程中的建議:當(dāng)需要重載函數(shù)模板的時(shí)候,我們要優(yōu)先考慮使用模板特化的方式去分開(kāi)實(shí)現(xiàn)一個(gè)函數(shù)模板,而是不用重載函數(shù)模板的方式去新的實(shí)現(xiàn)了一個(gè)函數(shù),當(dāng)模板特化無(wú)法滿(mǎn)足要
求的時(shí)候,在使用函數(shù)重載。

工程中使用模板特化來(lái)代替類(lèi)(函數(shù))重定義。


例:類(lèi)模板的部分特化、完全特化,函數(shù)模板的完全特化。優(yōu)先考慮使用特化的方式當(dāng)需要將模板進(jìn)行重定義添加功能時(shí)。

#include <iostream>
#include <string>

using namespace std;


/*
*	特化的方式實(shí)現(xiàn)一個(gè)類(lèi)模板,本質(zhì)就是分開(kāi)實(shí)現(xiàn)類(lèi)模板
*
*/
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>	//為類(lèi)模板的部分特化
{
public:
	void print(T a, T b)
	{
		cout << "void print(T a, T b)" << endl;
		cout << a << " " << b << endl;
	}	
};

template
< >
class Why<int, int>		//為類(lèi)模板的完全特化
{
public:
		void print(int a, int b)
		{
			cout << "void print(int a, int b)" << endl;
			cout << a << " " << b << endl;
		}
};

/*
*	函數(shù)模板的特化只支持完全特化
*	實(shí)現(xiàn)一個(gè)函數(shù)模板,并且完全特化,也就是分開(kāi)實(shí)現(xiàn)一個(gè)函數(shù)模板,這樣叫做特化。
*/
template 
<typename T>
bool Equal(T a, T b)
{
	return a == b;
}

template
< >		//函數(shù)模板的完全特化,之所以要特化這個(gè)函數(shù)模板是因?yàn)?,浮點(diǎn)數(shù)的比較不單純的只用==來(lái)比較。
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ù)的方式來(lái)達(dá)到比較浮點(diǎn)數(shù)的方法,但這種方式是不優(yōu)先考慮的,因?yàn)檫@種方式,在使用的時(shí)候要考慮如何選擇,要優(yōu)先考慮使用特化的方式。
*	能使用特化的方式時(shí),就不考慮使用這種函數(shù)重載的方式,不論對(duì)于類(lèi)模板還是函數(shù)模板都是這樣的,優(yōu)先考慮使用特化的方式來(lái)分開(kāi)實(shí)現(xiàn),因?yàn)檫@樣都是為了實(shí)現(xiàn)一個(gè)類(lèi)模板或函數(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++類(lèi)模板深度剖析
分享路徑:http://jinyejixie.com/article48/gpesep.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供App設(shè)計(jì)、定制開(kāi)發(fā)、網(wǎng)站設(shè)計(jì)公司網(wǎng)站策劃、微信小程序、

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

網(wǎng)站建設(shè)網(wǎng)站維護(hù)公司
通河县| 和平县| 白水县| 渭源县| 淳安县| 郁南县| 昌江| 玉田县| 紫金县| 民乐县| 济阳县| 资中县| 罗江县| 自治县| 长顺县| 华蓥市| 东山县| 寿宁县| 体育| 乌鲁木齐县| 福贡县| 饶平县| 乳山市| 鄂托克旗| 始兴县| 南木林县| 商丘市| 南乐县| 常州市| 西乌| 泌阳县| 林周县| 山阴县| 靖安县| 萨嘎县| 翼城县| 武汉市| 沙坪坝区| 光山县| 迁西县| 于田县|