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

【C++泛型學(xué)習(xí)筆記】類模板、變量模板和別名模板-創(chuàng)新互聯(lián)

學(xué)習(xí)參考書籍:王健偉《C++新經(jīng)典:模板與泛型編程》

創(chuàng)新互聯(lián)網(wǎng)站建設(shè)服務(wù)商,為中小企業(yè)提供成都網(wǎng)站建設(shè)、網(wǎng)站設(shè)計服務(wù),網(wǎng)站設(shè)計,網(wǎng)站托管維護等一站式綜合服務(wù)型公司,專業(yè)打造企業(yè)形象網(wǎng)站,讓您在眾多競爭對手中脫穎而出創(chuàng)新互聯(lián)。
類模板

和函數(shù)模板一樣,類模板可以理解為產(chǎn)生類的模具,通過給定的模板參數(shù)生成具體的類。vector容器就是一個類模板應(yīng)用的例子,vector可以存放不同類型的數(shù)據(jù)類型元素,其就是通過引入類模板來減少不同類型元素存儲時重復(fù)的代碼,代碼更加精簡和通用。示例如下:

#includeusing namespace std;

template//標(biāo)識符為T的模板參數(shù),表示myvector容器所保存的元素類型
class myvector
{public:
	typedef T* myiterator;	// 迭代器
public:
	myvector();	//構(gòu)造函數(shù)
    myvector(T tmpt) // 帶參數(shù)的構(gòu)造函數(shù)
    {
    }
	myvector& operator=(const myvector&);	// 重載賦值運算符,在類模板中使用模板名可以不用提供模板參數(shù),如myvectorpublic:
	void myfunc()
	{cout<< "mufunc() 被調(diào)用"<< endl;
	}
public:
	// 迭代器接口
	myiterator mybegin();	//迭代器起始位置
	myiterator myend();		//迭代器結(jié)束位置	
};

templatemyvector::myvector()		// 類外構(gòu)造函數(shù)實現(xiàn)
{}


int main()
{myvectortempvec;	//T被替換成int,即指定模板參數(shù)T為int
    myvector tempvec1(6);    // 不用指定模板參數(shù)
	tempvec.myfunc();		//調(diào)用類模板中的普通成員函數(shù)
}

對于類模板myvector,myvector稱為類名或類模板,myvector稱為類型名,其中T稱為模板參數(shù),T本身代表容器中的元素類型。在類模板內(nèi)部類型名可以簡寫成類名,如myvector& operator=(const myvector&);,但在類模板外不可以,如myvector::myvector()。

對于類模板的模板參數(shù)推導(dǎo),代碼myvector tempvec1(6);中,我們通過調(diào)用含參數(shù)的構(gòu)造函數(shù)實例化模板類,編譯器通過傳入的實參類型可以自動推導(dǎo)出T的類型。而myvectortempvec;則是通過類名<類型>指定T的類型(倘若沒有帶參數(shù)的構(gòu)造函數(shù),T仍需指定)。實現(xiàn)模板參數(shù)推導(dǎo)的功能是通過使用推斷指南(deduction guide),其作用為推斷類模板參數(shù)時提供推斷指引。一般我們常見的(如上面代碼中的例子)都為隱式推斷指南,無需指定(前提是待傳入?yún)?shù)的構(gòu)造函數(shù)存在)編譯器自動推斷。當(dāng)然,程序員也可以自定義推斷指南(如不存在構(gòu)造函數(shù)的情況)。形式如下:

templateA(T,T)->A;

對于類模板的特化。類模板的全特化如下:

template<>class  myvector{public:
	myvector()
	{cout<< "全特化版本"<< endl;
	}

	void myfunc();
};

void myvector::myfunc()
{cout<< "全特化版本的myfunc"<< endl;
}

int main()
{myvectortempvec;	
	tempvec.myfunc();
}

需要區(qū)分的是,泛化版本的類模板和全特化版本的類模板只是同名,兩者實例化后的對象是完全不同的兩個類,即成員屬性和函數(shù)無法共享。其次對在全特化版本類模板外定義的成員函數(shù)不能在開頭加template<>,相當(dāng)于全特化后變成了一個普通類。

普通成員函數(shù)和靜態(tài)變量的全特化如下:

#includeusing namespace std;

template//標(biāo)識符為T的模板參數(shù),表示myvector容器所保存的元素類型
class myvector
{public:
	typedef T* myiterator;	// 迭代器
	static int m_stc;	// 靜態(tài)變量聲明
public:
	myvector();	//構(gòu)造函數(shù)
	myvector(T tmpt) // 帶參數(shù)的構(gòu)造函數(shù)
	{}
	myvector& operator=(const myvector&);	// 重載賦值運算符,在類模板中使用模板名可以不用提供模板參數(shù),如myvectorpublic:
	void myfunc();

public:
	// 迭代器接口
	myiterator mybegin();	//迭代器起始位置
	myiterator myend();		//迭代器結(jié)束位置	
};

templatemyvector::myvector()		// 類外構(gòu)造函數(shù)實現(xiàn)
{cout<< "泛化版本的構(gòu)造函數(shù)被調(diào)用"<< endl;
}

template<>class  myvector{public:
	myvector()
	{cout<< "全特化版本"<< endl;
	}

	void myfunc();
};

void myvector::myfunc()
{cout<< "全特化版本的myfunc"<< endl;
}

templatevoid myvector::myfunc()
{cout<< "泛化版本的普通成員函數(shù)myfunc()被調(diào)用"<< endl;
}

template<>void myvector::myfunc()
{cout<< "泛化版本的普通成員函數(shù)myfunc()的全特化版本被調(diào)用"<< endl;
}

templateint myvector::m_stc = 10;

template<>int myvector::m_stc = 100;


int main()
{myvectortempvec;	
	tempvec.myfunc();
	cout<< tempvec.m_stc<< endl;
}

在上述代碼的mian函數(shù)中,我們使用myvectortempvec;指令模板參數(shù)類型為float實例化了類模板,因為myvector類模板存在全特化版本,所以編譯器會先找到全特化版本,但是由于全特化版本中模板參數(shù)特化類型為int,class myvector,所以只能使用泛化版本,因此運行的是泛化版本的構(gòu)造函數(shù)。接著,運行代碼tempvec.myfunc();,tempvec是泛化版本示例化后的類,所以myfunc函數(shù)也是泛化版本中的,不過在泛化版本中存在全特化的同名函數(shù),所以會優(yōu)先選擇其。不過由于該成員函數(shù)的全特化版本模板參數(shù)類型為double,void myvector::myfunc(),不是該實例化類中模板參數(shù)float,所以該全特化函數(shù)不會取代原來的同名成員函數(shù)。對于模板類中的靜態(tài)變量m_stc同理。亦然,我們?nèi)绻铋_始指定模板類型為double,那么會依次執(zhí)行泛化版本的構(gòu)造函數(shù),泛化版本的全特化myfunc成員函數(shù),輸出泛化版本的m_stc靜態(tài)變量。想一想,如果實例化類的模板參數(shù)類型為int,那么cout<< tempvec.m_stc<< endl;必然會報錯,因為類模板的全特化版本中沒有這一靜態(tài)變量。

注意:如果進行了普通成員函數(shù)或靜態(tài)成員變量的全特化,那么就無法用這些全特化時指定的類型對整個類模板進行全特化了。因為在對成員函數(shù)或靜態(tài)成員變量進行了全特化后導(dǎo)致實例化了對應(yīng)類型的類模板,如果再次進行全特化,將不會重復(fù)進行相同類型的實例化,編譯器報錯。

對于類模板的偏特化有兩種:一是模板參數(shù)數(shù)量上的偏特化;一是模板參數(shù)范圍上的偏特化。具體實現(xiàn)和原理類似于函數(shù)模板的偏特化。

對于默認(rèn)參數(shù):

  • 與函數(shù)模板的默認(rèn)參數(shù)不同,類模板的默認(rèn)參數(shù)規(guī)定:如果某一模板參數(shù)具有默認(rèn)值,那么其后所有的模板參數(shù)都得有默認(rèn)值。
  • 有默認(rèn)值的模板參數(shù)在類模板實例化時可以不用提供,如myvector<>tmpvec。
  • 后面的模板參數(shù)可以依賴前面的模板參數(shù),如template
  • 還可以在模板聲明中指定默認(rèn)參數(shù)。

類型別名,可以通過typedef或者using關(guān)鍵字給類型名起一個別名。

typedef TCIF_TC;
using IF_TCU = TC;

和函數(shù)模板一樣,類模板中同樣也可以有非類型模板參數(shù),但全局指針、浮點數(shù)和字符串常量不能作為非類型模板參數(shù)。

成員函數(shù)模板

示例如下:

#includeusing namespace std;

templateclass A 
{public:
	A(double v1, double v2)	// 普通構(gòu)造函數(shù)
	{cout<< "A::A(double,double)執(zhí)行了!"<< endl;
	}
	A(T1 v1, T1 v2)		// 使用類模板參數(shù)類型的構(gòu)造函數(shù)
	{cout<< "A::A(T1,T1)執(zhí)行了!"<< endl;
	}
	templateA(T2 v1, T2 v2);	// 構(gòu)造函數(shù)模板

	templatevoid myfunc(T3 tmpt)	// 普通成員函模板
	{cout<< tmpt<< endl;
	}
	T1 m_ic;
	static constexpr int m_stcvalue = 200;
};

// 在類外實現(xiàn)類模板的構(gòu)造函數(shù)模板
template// 先寫類模板的模板參數(shù)列表
template// 再寫構(gòu)造函數(shù)模板自己的模板參數(shù)列表
A::A(T2 v1, T2 v3)
{cout<< "A::A(T2,T2)執(zhí)行了!"<< endl;
}


int main()
{Aa(1, 2);
	a.myfunc(3);
}
  • 類模板中的成員函數(shù),只有在源代碼中調(diào)用時,對應(yīng)成員函數(shù)才會出現(xiàn)在實例化的類模板中。
  • 類模板中的成員函數(shù)模板,只有在源代碼中調(diào)用時,對應(yīng)成員函數(shù)模板的具體實例才會出現(xiàn)在實例化的類模板中。
  • 編譯器目前不支持虛成員函數(shù)模板。

拷貝構(gòu)造函數(shù)模板不等同且永遠(yuǎn)不可能成為拷貝構(gòu)造函數(shù),拷貝賦值運算符模板不等同且永遠(yuǎn)不可能成為拷貝賦值運算符。類型相同的對象拷貝構(gòu)造調(diào)用的是拷貝構(gòu)造函數(shù),類型不同的對象拷貝構(gòu)造調(diào)用的是拷貝構(gòu)造函數(shù)模板,并不會因為找不到對應(yīng)調(diào)用對象而且調(diào)用另一個。

對于成員函數(shù)模板也具有特化版本。

相關(guān)資料表示,C++標(biāo)準(zhǔn)不允許在類模板之外全特化一個未被全特化的類模板的成員函數(shù)模板。即在類模板外,如果要全特化一個成員函數(shù)模板,需要確保該成員函數(shù)模板所屬的類模板為全特化版本。

類模板嵌套

類模板中套類模板和類中類相差不大。需要注意的是,將子類模板的成員函數(shù)寫在父類模板的泛化版本之外,應(yīng)當(dāng)如下形式:

template//父類模板參數(shù)列表
template//子類模板參數(shù)列表
void A::B::myfunc()
{}
變量模板與成員變量模板

變量模板定義和使用如下:

#includeusing namespace std;

templateT myvar{};	// 變量模板,{}為零初始化

int main()
{myvar= 13;
	myvar= 13.1;
	cout<< myvar<< " "<< myvar<< endl;
}

不同的指定類型得到不同的變量。

templateT myvar{};	// 泛化版本

template<>char myvar{};	// 全特化版本,myvar可以當(dāng)作char類型使用

templateT myvar{120};	// 偏特化版本

templateT myvar{};		// 默認(rèn)模板參數(shù)

templateT myvar[val];		// 非類型模板參數(shù)

templateclass A
{public:
	templatestatic W m_tpi;		// 成員變量模板
};

// 成員變量模板在類模板外定義
templatetemplateW A::m_tpi = 5;
別名模板與成員別名模板

別名模板的作用主要是簡化書寫。

#includetemplateusing str_map_t = std::map;	// 別名模板

templateclass A
{templateusing str_map_t = std::map;	// 成員別名模板
public:
    str_map_tmap1;
};

int main()
{str_map_tmap1;
    map1.insert({'one', 1});
    map1.insert({'two', 2});
    Aobja;
    obja.map1.insert({'one', 1});
}
模板模板參數(shù)

之前我們學(xué)習(xí)的模板參數(shù)有類型模板參數(shù)和非類型模板參數(shù),這一部分將提出模板模板參數(shù),即模板參數(shù)本身為模板,將類模板當(dāng)作參數(shù)傳遞到另一個模板中。我們在學(xué)習(xí)類模板的時候知道vector、list等容器類其實也是類模板,所以若我們想要將這些容器類作為模板參數(shù)傳入模板中,寫法如下:

#include#include#includeusing namespace std;

templateclass Container = std::vector>//templatetypename Container = std::vector>class myclass
{public:
	Containermyc;
public:
	void func();
	myclass()
	{for (int i = 0; i< 10; i++)
		{	myc.push_back(i);	// 本行代碼正確性取決于模板參數(shù)類型
		}
	}
};

templateclass Container>void myclass::func()
{cout<< "mstifiy"<< endl;
}

int main()
{myclassmylistobj; // double是容器中的元素類型,list是容器類型
	mylistobj.func();
	std::cout<< mylistobj.myc.size()<< endl;
}

其中重點注意模板參數(shù)列表的寫法:

templateclass Container = std::vector>templatetypename Container = std::vector>// class也能替換成typename修飾
templatetypename Container = std::vector>// W為容器模板的類型模板參數(shù),不能用,故省略
templatetypename Container>// 沒有默認(rèn)模板參數(shù)

class和typename可以相互替代,都是合法的。

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧

本文名稱:【C++泛型學(xué)習(xí)筆記】類模板、變量模板和別名模板-創(chuàng)新互聯(lián)
本文網(wǎng)址:http://jinyejixie.com/article46/isceg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供微信公眾號、用戶體驗、企業(yè)建站、定制開發(fā)、品牌網(wǎng)站制作、網(wǎng)站設(shè)計

廣告

聲明:本網(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)

阿坝县| 怀宁县| 外汇| 方山县| 苏尼特右旗| 博客| 白水县| 隆昌县| 莱西市| 苍南县| 高邑县| 甘孜县| 焉耆| 滨州市| 兴和县| 阳新县| 乐东| 永春县| 民县| 淳安县| 东莞市| 年辖:市辖区| 南皮县| 微博| 凉城县| 宜川县| 罗甸县| 罗江县| 民县| 库伦旗| 鲁甸县| 井冈山市| 赤城县| 三原县| 灌云县| 和田县| 奉贤区| 施甸县| 长治县| 葫芦岛市| 百色市|