国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

突破編程_C++_高級(jí)教程(模板編程的基礎(chǔ)知識(shí))

這篇具有很好參考價(jià)值的文章主要介紹了突破編程_C++_高級(jí)教程(模板編程的基礎(chǔ)知識(shí))。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

1 模板編程的基本概念

C++ 的模板編程是一種編程技術(shù),它允許程序員編寫處理不同類型數(shù)據(jù)的通用代碼。通過使用模板,可以創(chuàng)建與特定數(shù)據(jù)類型無(wú)關(guān)的函數(shù)或類,這些函數(shù)或類在編譯時(shí)可以根據(jù)需要生成特定數(shù)據(jù)類型的版本。這增加了代碼的復(fù)用性、靈活性和類型安全性。

1.1 模板編程的本質(zhì)

從本質(zhì)上來說, C++ 的模板編程是一種編譯時(shí)多態(tài)性( compile-time polymorphism )的機(jī)制。在 C++ 中,多態(tài)性通常指的是以統(tǒng)一的方式處理不同類型的數(shù)據(jù)或?qū)ο蟮哪芰?。運(yùn)行時(shí)多態(tài)性( runtime polymorphism )通常通過虛函數(shù)實(shí)現(xiàn),它允許在運(yùn)行時(shí)根據(jù)對(duì)象的實(shí)際類型來調(diào)用不同的函數(shù)。而編譯時(shí)多態(tài)性則通過模板實(shí)現(xiàn),它允許在編譯時(shí)根據(jù)所使用的數(shù)據(jù)類型來生成不同的代碼。
模板編程的本質(zhì)可以歸結(jié)為以下幾點(diǎn):
類型參數(shù)化
模板允許程序員定義接受類型作為參數(shù)的函數(shù)或類。這些類型參數(shù)在模板實(shí)例化時(shí)被具體的數(shù)據(jù)類型所替換,從而生成特定類型的代碼。這種類型參數(shù)化使得代碼能夠以一種類型無(wú)關(guān)的方式編寫,提高了代碼的復(fù)用性和靈活性。
編譯時(shí)生成
模板實(shí)例化發(fā)生在編譯時(shí),編譯器根據(jù)提供的類型參數(shù)生成特定類型的函數(shù)或類的代碼。這意味著在編譯時(shí)就確定了函數(shù)或類的具體實(shí)現(xiàn),而不是在運(yùn)行時(shí)。這種編譯時(shí)生成的方式使得模板編程具有很高的性能優(yōu)勢(shì)。
類型安全
由于模板實(shí)例化是在編譯時(shí)進(jìn)行的,編譯器能夠?qū)︻愋瓦M(jìn)行嚴(yán)格的檢查,確保類型安全。這意味著在編譯時(shí)就能夠發(fā)現(xiàn)類型錯(cuò)誤,而不是等到運(yùn)行時(shí)才出現(xiàn)錯(cuò)誤。
泛型編程
模板編程是一種泛型編程的形式,它允許程序員編寫與具體數(shù)據(jù)類型無(wú)關(guān)的通用代碼。這種泛型編程的能力使得代碼更加簡(jiǎn)潔、易讀和可維護(hù)。
元編程能力
模板編程還具有元編程的能力,即利用模板在編譯時(shí)進(jìn)行編程。這包括模板特化、模板偏特化、遞歸模板等技術(shù),它們?cè)试S程序員在編譯時(shí)進(jìn)行復(fù)雜的邏輯判斷和代碼生成。
綜上所述, C++ 的模板編程的本質(zhì)是一種編譯時(shí)多態(tài)性的機(jī)制,它允許程序員以類型無(wú)關(guān)的方式編寫通用代碼,并在編譯時(shí)生成特定類型的代碼。這種機(jī)制提高了代碼的復(fù)用性、靈活性和性能,同時(shí)保證了類型安全。通過模板編程,程序員能夠編寫出更加優(yōu)雅、高效和可維護(hù)的代碼。

1.2 模板編程的應(yīng)用場(chǎng)景

C++ 模板編程支持使用通用代碼處理多種數(shù)據(jù)類型。這種編程模式在多個(gè)應(yīng)用場(chǎng)景中都非常有用,以下是 C++ 模板編程的一些典型應(yīng)用場(chǎng)景:
數(shù)據(jù)類型與算法相分離的泛型編程
這是模板編程最常見的應(yīng)用之一。通過將數(shù)據(jù)類型與算法分離,我們可以實(shí)現(xiàn)泛型編程,使代碼能夠處理多種數(shù)據(jù)類型而無(wú)需重復(fù)編寫。例如,在STL(標(biāo)準(zhǔn)模板庫(kù))中,容器(如std::vector、std::list)和算法(如std::sort、std::find)都是通過模板實(shí)現(xiàn)的,這使得它們可以與任何數(shù)據(jù)類型一起使用,從而大大提高了代碼的重用性。
類型適配( Traits )
類型適配是模板編程中的另一個(gè)重要概念。通過使用特性( Traits )模板,我們可以根據(jù)數(shù)據(jù)類型提供特定的類型信息或行為。這在需要根據(jù)數(shù)據(jù)類型執(zhí)行不同操作時(shí)非常有用。例如,根據(jù)數(shù)據(jù)類型是否為指針或引用,可以提供不同的類型適配實(shí)現(xiàn)。
函數(shù)轉(zhuǎn)發(fā)
函數(shù)轉(zhuǎn)發(fā)是 C++11 引入的一種新特性,它允許我們編寫能夠轉(zhuǎn)發(fā)其參數(shù)給另一個(gè)函數(shù)的模板函數(shù)。這在創(chuàng)建通用函數(shù)包裝器或代理時(shí)非常有用。通過使用函數(shù)轉(zhuǎn)發(fā),我們可以編寫一個(gè)模板函數(shù),該函數(shù)能夠?qū)⑵鋮?shù)以正確的方式轉(zhuǎn)發(fā)給另一個(gè)函數(shù),而無(wú)需知道目標(biāo)函數(shù)的具體簽名。
元編程
模板元編程是 C++ 模板編程的高級(jí)應(yīng)用之一。它允許我們?cè)诰幾g時(shí)執(zhí)行一系列的邏輯判斷和計(jì)算。元編程通常用于常量計(jì)算、類型操作和策略模式等場(chǎng)景。例如,可以使用遞歸模板來實(shí)現(xiàn)編譯時(shí)的階乘計(jì)算,或者使用模板特化來實(shí)現(xiàn)不同類型的特定行為。
編譯時(shí)容器與算法
通過模板元編程,我們還可以實(shí)現(xiàn)編譯時(shí)的容器和算法。這意味著在編譯階段就可以生成針對(duì)特定數(shù)據(jù)類型的容器和算法實(shí)現(xiàn),從而在運(yùn)行時(shí)獲得更高的性能。例如,我們可以使用模板元編程實(shí)現(xiàn)編譯時(shí)的靜態(tài)數(shù)組和排序算法。
策略模式
策略模式是一種設(shè)計(jì)模式,它允許程序在運(yùn)行時(shí)根據(jù)需要選擇不同的算法實(shí)現(xiàn)。通過模板編程,可以實(shí)現(xiàn)類似的功能,但在編譯時(shí)進(jìn)行選擇。這有助于提高代碼的靈活性和可擴(kuò)展性。
跨平臺(tái)編程
在跨平臺(tái)編程中,由于不同平臺(tái)可能使用不同的數(shù)據(jù)類型和大小,使用模板可以確保代碼在不同平臺(tái)上的兼容性和可移植性。通過編寫與平臺(tái)無(wú)關(guān)的模板代碼,我們可以更容易地在多個(gè)平臺(tái)上編譯和運(yùn)行程序。
綜上所述, C++ 模板編程在多個(gè)應(yīng)用場(chǎng)景中都發(fā)揮著重要作用,包括數(shù)據(jù)類型與算法相分離的泛型編程、類型適配、函數(shù)轉(zhuǎn)發(fā)、元編程、編譯時(shí)容器與算法、策略模式以及跨平臺(tái)編程等。這些應(yīng)用場(chǎng)景共同展示了模板編程在提高代碼重用性、類型安全性、性能和靈活性方面的優(yōu)勢(shì)。

2 函數(shù)模板

函數(shù)模板是一種特殊的函數(shù)定義,它使用模板參數(shù)來指定函數(shù)可以處理的數(shù)據(jù)類型。模板參數(shù)在函數(shù)定義中以類型參數(shù)的形式出現(xiàn),它們可以是任何有效的 C++ 數(shù)據(jù)類型,包括內(nèi)置類型和用戶定義的類型。

2.1 函數(shù)模板的定義和實(shí)例化

函數(shù)模板的定義包含了一個(gè)或多個(gè)類型參數(shù),這些類型參數(shù)在函數(shù)定義中以 typename 或 class 關(guān)鍵字進(jìn)行聲明。這些類型參數(shù)在函數(shù)體內(nèi)部被當(dāng)作普通的數(shù)據(jù)類型來使用。
函數(shù)模板的定義
函數(shù)模板的一般定義形式如下:

template <typename T1, typename T2, ..., typename Tn>  
return_type functionName(parameterList)
{  
    // 函數(shù)體  
}

其中 T1, T2, …, Tn 是類型參數(shù),代表可以是任何數(shù)據(jù)類型的占位符。return_type 是函數(shù)的返回類型, functionName 是函數(shù)的名稱, parameterList 是函數(shù)的參數(shù)列表。
如下是一個(gè)簡(jiǎn)單的函數(shù)模板示例,該模板定義了一個(gè)加法函數(shù):

template <typename T>  
T add(const T& a, const T& b) 
{  
    return a+b; 
}

在上面代碼中, T 是一個(gè)類型參數(shù),它可以是任何數(shù)據(jù)類型。 add 函數(shù)接受兩個(gè)類型為 T 的引用參數(shù),并返回它們相加的值。
函數(shù)模板的實(shí)例化
當(dāng)函數(shù)模板被調(diào)用時(shí),編譯器會(huì)根據(jù)提供的實(shí)際參數(shù)類型來推斷類型參數(shù)的具體類型,并生成一個(gè)具體的函數(shù)實(shí)例,這個(gè)過程稱為函數(shù)模板的實(shí)例化。
例如,如果使用 int 類型來調(diào)用上面的 add 函數(shù)模板:

int a = 1;  
int b = 2;  
int sum = add(a, b); // 這里會(huì)實(shí)例化一個(gè) int 類型的 add 函數(shù)

編譯器會(huì)生成一個(gè)專門處理 int 類型的 add 函數(shù)實(shí)例:

int add(const int& a, const int& b) 
{  
    return a+b; 
}

同樣地,如果使用 double 類型來調(diào)用 add 函數(shù)模板,編譯器會(huì)生成一個(gè)處理 double 類型的函數(shù)實(shí)例。
顯式實(shí)例化
除了隱式地通過函數(shù)調(diào)用進(jìn)行實(shí)例化外,我們還可以顯式地要求編譯器為特定的類型生成函數(shù)模板的實(shí)例。這通常在編譯時(shí)性能優(yōu)化或者某些特殊場(chǎng)景下是有用的。
顯式實(shí)例化的語(yǔ)法如下:

template void functionName<T>(parameterList);

對(duì)于上面的 add 函數(shù)模板,如果想要顯式地實(shí)例化一個(gè)處理 int 類型的版本,可以這樣做:

template int add<int>(const int&, const int&);

顯式實(shí)例化通常是在頭文件中完成的,以確保在多個(gè)源文件中使用時(shí)鏈接器可以找到正確的實(shí)例。

2.2 函數(shù)模板的自動(dòng)類型推導(dǎo)

函數(shù)模板的自動(dòng)類型推導(dǎo)是一種編譯器特性,它允許在調(diào)用函數(shù)模板時(shí)自動(dòng)確定模板參數(shù)的類型。這種自動(dòng)類型推導(dǎo)機(jī)制極大地簡(jiǎn)化了代碼,并提高了代碼的可讀性和可維護(hù)性。
在調(diào)用一個(gè)函數(shù)模板時(shí),編譯器會(huì)根據(jù)傳遞給函數(shù)的實(shí)際參數(shù)來推導(dǎo)模板參數(shù)的類型。這個(gè)過程通常被稱為模板參數(shù)的類型推導(dǎo)或類型推斷。

2.2.1 自動(dòng)類型推導(dǎo)的基本使用

如下為樣例代碼:

#include <iostream>  

template <typename T>
T add(const T& a, const T& b)
{
	return a + b;
}

int main() 
{
	int sum1 = add(1, 2);
	double sum2 = add(1.1, 2.1);

	return 0;
}

在上面代碼中,add 是一個(gè)函數(shù)模板,它接受兩個(gè)類型為 T 的參數(shù),并返回它們的和。類型 T 是一個(gè)模板參數(shù),代表可以是任何數(shù)據(jù)類型的占位符。
當(dāng)調(diào)用這個(gè)函數(shù)模板時(shí),編譯器會(huì)自動(dòng)推導(dǎo)類型 T 。在第一個(gè)調(diào)用 add(1, 2) 中,編譯器能夠推導(dǎo)出 T 的類型為 int,因?yàn)閮蓚€(gè)參數(shù)都是整數(shù)。類似地,在第二個(gè)調(diào)用 add(1.1, 2.1) 中,編譯器推導(dǎo)出 T 的類型為 double ,因?yàn)閮蓚€(gè)參數(shù)都是浮點(diǎn)數(shù)。類型推導(dǎo)的規(guī)則通常是針對(duì)直觀的數(shù)據(jù)類型,但是當(dāng)涉及到引用、指針、模板中包含多個(gè)類型時(shí),上面代碼中的簡(jiǎn)單自動(dòng)類型推導(dǎo)有可能會(huì)無(wú)法滿足。此時(shí)就需要使用 C++11 的新特性來處理。

2.2.2 使用 decltype 與 auto

C++11 及其之后的版本引入了更強(qiáng)大的類型推導(dǎo)機(jī)制,即 decltype 和 auto 的聯(lián)合使用,可以進(jìn)一步簡(jiǎn)化代碼并提高類型推導(dǎo)的靈活性。
如下為樣例代碼:

#include <iostream>  

template <class A, class B>
auto add(A a, B b) -> decltype(a + b)
{
	return a + b;
}

int main() 
{
	auto sum1 = add(1, 2);
	auto sum2 = add(1.1, 2.1);

	return 0;
}

在上面中,decltype(a + b) 允許編譯器推導(dǎo)返回值的類型,而不僅僅是函數(shù)參數(shù)的類型。在這個(gè)場(chǎng)景下,sum1 與 sum2 的類型分別被推導(dǎo)為 int 與 double 。
C++14 支持的語(yǔ)法 decltype(auto) 更為簡(jiǎn)潔,可以將上面代碼中的函數(shù)模板修改為:

template <class A, class B>
decltype(auto) add(A a, B b)
{
	return a + b;
}

使用 decltype 與 auto 尤其對(duì)模板函數(shù)中引用與 const 限定符的處理更為有效,如下為樣例代碼:

#include <iostream>  

template <typename T>
void func(T&& t) 
{
	decltype(t) val = t; // a 的類型與 t 相同,包括引用和 const 限定符  
	// ...  
}

int main() 
{
	int a = 1;
	const int& b = a;

	func(a); // t 的類型為 int& , val 的類型也為 int&  
	func(b); // t 的類型為 const int& , val 的類型也為 const int&  

	return 0;
}

在這個(gè)例子中,函數(shù)模板 func 接受一個(gè)右值引用參數(shù) t ,并使用 decltype(t) 來聲明一個(gè)局部變量 val ,其類型與 t 完全相同,包括引用和 const 限定符。這允許函數(shù)模板在處理不同類型的參數(shù)時(shí)保持更高的靈活性。

2.3 函數(shù)模板的顯式類型指定

函數(shù)模板的顯式類型指定是指在調(diào)用函數(shù)模板時(shí)明確指定模板參數(shù)的類型。這通常在希望消除類型推導(dǎo)的歧義或明確指定一個(gè)類型而不是讓編譯器自動(dòng)推導(dǎo)時(shí)非常有用。
使用顯式類型指定的語(yǔ)法是在函數(shù)名后面的尖括號(hào) < > 中直接列出模板參數(shù)類型。這允許你在調(diào)用模板函數(shù)時(shí)提供具體的類型,即使這些類型可以從傳遞給函數(shù)的參數(shù)中推導(dǎo)出來。
如下為樣例代碼:

#include <iostream>  
#include <typeinfo>  

template <typename T1, typename T2>
decltype(auto) add(T1 t1, T2 t2)
{
	return t1 + t2;
}

int main() 
{
	auto sum1 = add(1, 2);
	printf("type of sum1 is %s\n", typeid(sum1).name());

	auto sum2 = add<double, double>(1, 2);
	printf("type of sum2 is %s\n", typeid(sum2).name());

	return 0;
}

上面代碼的輸出為:

type of sum1 is int
type of sum2 is double

在這個(gè)例子中,add 是一個(gè)函數(shù)模板,它接受類型為 T1 、 T2 的參數(shù)。在 main 函數(shù)中,首先以正常方式調(diào)用 add 函數(shù),讓編譯器從傳遞給函數(shù)的參數(shù)中推導(dǎo)出 T 的類型,最后的返回類型為 int 。然后,顯式地指定了 T 的類型,最后的返回類型為 double 。

2.4 函數(shù)模板的特化

函數(shù)模板的特化(Function Template Specialization)是C++模板編程中的一個(gè)重要概念,它支持為特定的類型或一組類型提供定制的模板實(shí)現(xiàn)。特化版本的函數(shù)模板會(huì)覆蓋通用模板的版本,當(dāng)使用特化類型調(diào)用函數(shù)模板時(shí),將使用特化版本的實(shí)現(xiàn)。
函數(shù)模板的特化通常指的是完全特化(類模板同時(shí)支持完全特化與部分特化),但是可以通過為特定的類型組合創(chuàng)建新的函數(shù)模板或重載現(xiàn)有的函數(shù)來實(shí)現(xiàn)部分特化的效果。
完全特化是指為函數(shù)模板提供一個(gè)完全限定的類型實(shí)現(xiàn)。這意味著為特定的類型提供了一個(gè)獨(dú)立的實(shí)現(xiàn),這個(gè)實(shí)現(xiàn)將僅適用于該類型。完全特化的語(yǔ)法與通用模板的語(yǔ)法類似,但在模板參數(shù)列表中使用具體的類型替代類型參數(shù)。
如下為樣例代碼:

#include <iostream>  

// 通用模板  
template <typename T1, typename T2>
decltype(auto) add(T1 t1, T2 t2)
{
	printf("call general template\n");
	return t1 + t2;
}

// 特化模板,僅適用于 int , int 類型  
template <>
decltype(auto) add<int>(int t1, int t2)
{
	printf("call specialized template for int , int\n");
	return t1 + t2;
}

int main() 
{	
	// 調(diào)用特化模板
	auto sum1 = add(1, 2);
	// 調(diào)用通用模板
	auto sum2 = add(1.2, 2.3);

	return 0;
}

上面代碼的輸出為:

call specialized template for int , int
call general template

在這個(gè)例子中,當(dāng) add 函數(shù)以 int 類型調(diào)用時(shí),將使用完全特化版本的實(shí)現(xiàn)。對(duì)于其他類型,如 double 或 std::string ,將使用通用模板的實(shí)現(xiàn)。
由于函數(shù)模板不支持部分特化,如果需要為一組類型提供特定的實(shí)現(xiàn),通常需要通過重載函數(shù)來實(shí)現(xiàn)類似的效果。這些函數(shù)具有與通用模板相同的名稱,但參數(shù)類型不同。
如下為樣例代碼:

#include <iostream>  

// 通用模板  
template <typename T1, typename T2>
decltype(auto) add(T1 t1, T2 t2)
{
	printf("call general template\n");
	return t1 + t2;
}

// 重載函數(shù),僅適用于 int ,int 類型  
decltype(auto) add(int t1, int t2)
{
	printf("call overloaded function for int , int\n");
	return t1 + t2;
}

// 重載函數(shù),僅適用于 double ,int 類型  
decltype(auto) add(double t1, int t2)
{
	printf("call overloaded function for double , int\n");
	return t1 + t2;
}

int main() 
{	
	// 調(diào)用重載函數(shù):int ,int
	auto sum1 = add(1, 2);
	// 調(diào)用重載函數(shù):double ,int
	auto sum2 = add(1.2, 2);
	// 調(diào)用通用模板
	auto sum3 = add(1.2, 2.3);

	return 0;
}

上面代碼的輸出為:

call overloaded function for int , int
call overloaded function for double , int
call general template

3 類模板

類模板允許定義可以在實(shí)例化時(shí)進(jìn)行指定數(shù)據(jù)類型的類。換句話說,類模板是一個(gè)參數(shù)化類型,它使用一個(gè)或多個(gè)參數(shù)來創(chuàng)建一系列類。
類模板的主要優(yōu)勢(shì)在于,它可以減少代碼重復(fù),提高編程效率。通過為一系列僅成員數(shù)據(jù)類型不同的類創(chuàng)建一個(gè)類模板,程序員只需提供一套程序代碼,就可以生成多種具體的類,這些類可以看作是類模板的實(shí)例。

3.1 類模板的定義和實(shí)例化

類模板的定義類似于函數(shù)模板的定義。在類模板中,可以指定一個(gè)或多個(gè)類型參數(shù),這些類型參數(shù)在實(shí)例化時(shí)將被實(shí)際的數(shù)據(jù)類型替代。
類模板的一般定義形式如下:

template <typename T> // T 是一個(gè)類型參數(shù)  
class MyClass 
{
public:

	MyClass(T val) : m_val(val) {} // 構(gòu)造函數(shù)也使用類型參數(shù) T  

	void printVal() 
	{
		std::cout << "value: " << m_val << std::endl;
	}

private:
	T m_val;        // 成員變量使用類型參數(shù) T  
};

在這個(gè)例子中,MyClass 是一個(gè)類模板,它有一個(gè)類型參數(shù) T 。T 是一個(gè)占位符,代表一種未指定的數(shù)據(jù)類型。在類模板的定義中,可以像使用普通數(shù)據(jù)類型一樣使用 T 。
要使用類模板,需要?jiǎng)?chuàng)建一個(gè)或多個(gè)該模板的實(shí)例。實(shí)例化類模板時(shí),需要為模板參數(shù)提供具體的數(shù)據(jù)類型。這可以通過在類模板名稱后的尖括號(hào) < > 中指定類型來完成。針對(duì)上面定義的模板類,可以做如下實(shí)例化:

int main() 
{
	// 實(shí)例化 MyClass 模板,T 被替換為 int  
	MyClass<int> obj1(1);
	obj1.printVal(); // 輸出: value: 1  

	// 實(shí)例化 MyClass 模板,T 被替換為 string  
	MyClass<std::string> obj2("hello");
	obj1.printVal(); // 輸出: value: hello 

	return 0;
}

在上面代碼中,為 MyClass 模板提供了兩種數(shù)據(jù)類型:int 和 std::string。每次提供一個(gè)新的數(shù)據(jù)類型,編譯器都會(huì)創(chuàng)建一個(gè)新的類類型。因此,MyClass<int> 和 MyClass<std::string> 是兩種不同的類類型,它們有各自的對(duì)象實(shí)例和方法。
注意事項(xiàng)
(1)類模板的實(shí)例化是隱式的,也就是說,當(dāng)創(chuàng)建一個(gè)對(duì)象時(shí),編譯器會(huì)自動(dòng)處理模板的實(shí)例化。
(2)模板參數(shù) T 在類模板的實(shí)例化時(shí)被實(shí)際類型替換,這種替換是在編譯時(shí)完成的,因此不會(huì)增加運(yùn)行時(shí)開銷。
(3)可以為類模板定義多個(gè)類型參數(shù),例如 template <typename T1, typename T2> ,這樣就可以在類中使用兩種不同類型的數(shù)據(jù)。
(4)類模板的實(shí)例化會(huì)產(chǎn)生新的類類型,這些類型之間是相互獨(dú)立的,除了它們共享相同的模板定義外。

3.2 類模板的構(gòu)造函數(shù)和析構(gòu)函數(shù)

在類模板中,構(gòu)造函數(shù)和析構(gòu)函數(shù)的定義與處理常規(guī)類的方式類似。類模板的構(gòu)造函數(shù)用于初始化模板類的對(duì)象,而析構(gòu)函數(shù)用于在對(duì)象生命周期結(jié)束時(shí)釋放資源。
構(gòu)造函數(shù)
構(gòu)造函數(shù)是特殊類型的成員函數(shù),它在創(chuàng)建類的新對(duì)象時(shí)自動(dòng)調(diào)用。類模板的構(gòu)造函數(shù)在實(shí)例化時(shí)會(huì)用實(shí)際的類型參數(shù)替換模板參數(shù),以便正確地進(jìn)行初始化。
下面是一個(gè)類模板的例子,其中包含了構(gòu)造函數(shù):

template <typename T>
class MyClass {
public:
	// 構(gòu)造函數(shù)  
	MyClass(T val) : m_val(val) {}

	// 其他成員函數(shù)...  

private:
	T m_val;
};

在這個(gè)例子中,MyClass 的構(gòu)造函數(shù)接受一個(gè)類型為 T 的參數(shù) val ,并用它來初始化私有成員變量 m_val 。
析構(gòu)函數(shù)
析構(gòu)函數(shù)是當(dāng)對(duì)象的生命周期結(jié)束時(shí)自動(dòng)調(diào)用的特殊成員函數(shù)。在類模板中,析構(gòu)函數(shù)通常用于釋放對(duì)象可能擁有的任何資源,如動(dòng)態(tài)分配的內(nèi)存。
下面是一個(gè)類模板的例子,其中包含了析構(gòu)函數(shù):

template <typename T>
class MyClass 
{
public:
	// 構(gòu)造函數(shù)  
	MyClass(T val) : m_val(new T(val)) { }

	// 析構(gòu)函數(shù)  
	~MyClass() 
	{
		delete m_val;
	}

	// 其他成員函數(shù)...  
private:
	T* m_val;
};

在這個(gè)例子中,MyClass 的析構(gòu)函數(shù)使用 delete 釋放了動(dòng)態(tài)分配的內(nèi)存。
實(shí)例化時(shí)的構(gòu)造函數(shù)和析構(gòu)函數(shù)調(diào)用
當(dāng)類模板被實(shí)例化并創(chuàng)建對(duì)象時(shí),相應(yīng)的構(gòu)造函數(shù)會(huì)被調(diào)用。同樣,當(dāng)對(duì)象離開其作用域或被顯式刪除時(shí),析構(gòu)函數(shù)會(huì)被調(diào)用。針對(duì)上面定義的模板類,可以做如下實(shí)例化的調(diào)用:

int main() 
{
	// 實(shí)例化 MyClass 模板,T 被替換為 int  
	MyClass<int> obj(1); // 調(diào)用 MyClass<int> 的構(gòu)造函數(shù)  
	// ... obj 被使用 ...  
	// 當(dāng) obj 離開作用域時(shí),MyClass<int> 的析構(gòu)函數(shù)會(huì)被調(diào)用  

	return 0;
}

在上面代碼中,obj 是 MyClass 類型的一個(gè)對(duì)象。當(dāng) obj1 被創(chuàng)建時(shí),MyClass 的構(gòu)造函數(shù)會(huì)被調(diào)用,而當(dāng) obj 離開其作用域時(shí),MyClass 的析構(gòu)函數(shù)會(huì)被調(diào)用。
注意:類模板的構(gòu)造函數(shù)和析構(gòu)函數(shù)在處理資源管理和初始化/清理工作時(shí)與常規(guī)類相同,只是它們需要能夠處理模板參數(shù) T 所代表的不同數(shù)據(jù)類型。

3.3 類模板的成員變量和成員函數(shù)

在類模板中,成員變量和成員函數(shù)的概念與常規(guī)類中的相同。成員變量用于存儲(chǔ)類的實(shí)例的狀態(tài),而成員函數(shù)則定義了可以對(duì)這些狀態(tài)執(zhí)行的操作。
成員變量
類模板的成員變量通常使用模板參數(shù) T(或其他模板參數(shù))作為它們的類型。這些變量在類的所有實(shí)例化中都是私有的、受保護(hù)的或公開的,具體取決于它們的訪問修飾符。
下面是一個(gè)類模板的例子,其中包含了由不同訪問修飾符修飾的成員變量:

template <typename T>
class MyClass 
{
	// 構(gòu)造函數(shù)和其他成員函數(shù)...  

	// 成員變量
private:
	// 私有成員變量  
	T m_privateVar;

protected:
	// 受保護(hù)成員變量  
	T m_protectedVar;

public:
	// 公開成員變量  
	T m_publicVar;
};

在上面代碼中,m_privateVar、m_protectedVar 和 m_publicVar 都是使用模板參數(shù) T 類型的成員變量。它們的訪問級(jí)別分別是私有、受保護(hù)和公開。
成員函數(shù)
類模板的成員函數(shù)定義了可以在類的實(shí)例上執(zhí)行的操作。這些函數(shù)可以訪問類的成員變量,并且可以使用模板參數(shù) T(或其他模板參數(shù))來執(zhí)行類型無(wú)關(guān)的操作。
如下為樣例代碼:

template <typename T>
class MyClass 
{
public:
	// 構(gòu)造函數(shù)  
	MyClass(T val) : m_val(val) {}

	// 成員函數(shù)  
	void setVal(T val) { m_val = val; }

	T getVal() const { return m_val; }

	// 其他成員函數(shù)...  
private:
	T m_val;
};

在上面代碼中,setVal 和 getVal 都是成員函數(shù)。setVal 接受一個(gè)類型為 T 的參數(shù),并設(shè)置 value 成員變量的值。getVal 則返回 value 的當(dāng)前值,并且由于它被聲明為 const,所以不能修改類的狀態(tài)。
成員函數(shù)的重載
與常規(guī)類一樣,也可以在類模板中重載成員函數(shù)。這意味著可以定義多個(gè)具有相同名稱但參數(shù)不同的成員函數(shù)。
如下為樣例代碼:

template <typename T1, typename T2>
class MyClass 
{
public:
	// 重載的成員函數(shù)  
	void setVal(T1 val) { m_val1 = val; }

	// 重載的成員函數(shù)  
	void setVal(T2 val) { m_val2 = val; }

	// 其他成員函數(shù)...  
private:
	T1 m_val1;
	T2 m_val2;
};

在上面代碼中,setVal 被重載了兩次:一次接受 T1 類型的參數(shù),另一次接受 T2 類型的參數(shù)。根據(jù)傳遞給函數(shù)的參數(shù)類型,編譯器會(huì)選擇適當(dāng)?shù)暮瘮?shù)版本進(jìn)行調(diào)用。

3.4 類模板的特化和偏特化

類模板的特化和偏特化是 C++ 模板編程中的兩個(gè)重要概念,它們?cè)试S為特定的類型或一組類型提供定制的模板實(shí)現(xiàn)。
特化
特化是指為模板提供一個(gè)完整的替代實(shí)現(xiàn),該實(shí)現(xiàn)僅適用于一個(gè)特定的類型。當(dāng)需要要改變某個(gè)類型在模板中的行為時(shí),則可以為這個(gè)類型創(chuàng)建一個(gè)特化版本。特化版本會(huì)覆蓋模板的通用實(shí)現(xiàn)。
如下為樣例代碼:

template <typename T>  
class MyClass 
{  
    // 通用實(shí)現(xiàn)  
};  
  
// 特化版本,僅適用于int類型  
template <>  
class MyClass<int> 
{  
    // int類型的特化實(shí)現(xiàn)  
};

在上面代碼中,MyClass 是一個(gè)模板類,它有一個(gè)通用實(shí)現(xiàn)。然后為 int 類型創(chuàng)建了一個(gè)特化版本,該版本將替代通用實(shí)現(xiàn)。
偏特化
偏特化允許為模板提供一個(gè)定制的實(shí)現(xiàn),該實(shí)現(xiàn)適用于一組特定的類型。與特化不同,偏特化不需要指定所有的模板參數(shù)。
如下為樣例代碼:

template <typename T1, typename T2>  
class MyClass 
{  
    // 通用實(shí)現(xiàn)  
};  
  
// 偏特化版本,僅適用于T1為int,T2為任意類型的情況  
template <typename T2>  
class MyClass<int, T2> 
{  
    // int, T2類型的偏特化實(shí)現(xiàn)  
};

在上面代碼中,為 MyClass 創(chuàng)建了一個(gè)偏特化版本,該版本僅當(dāng)?shù)谝粋€(gè)模板參數(shù) T1 是 int 類型時(shí)適用,而第二個(gè)模板參數(shù) T2 可以是任意類型。
注意事項(xiàng)
(1)特化和偏特化必須在模板定義之后聲明。
(2)特化和偏特化不能與原始模板在同一個(gè)頭文件中定義。
(3)偏特化不能比原始模板更加通用。例如,如果原始模板接受兩個(gè)類型參數(shù),偏特化就不能只接受一個(gè)。
(4)偏特化在編譯時(shí)的優(yōu)先級(jí)高于特化,也高于原始模板。
使用特化和偏特化可以顯著提高模板的靈活性和效率,但也需要謹(jǐn)慎使用,以避免產(chǎn)生復(fù)雜性和維護(hù)問題。

3.5 類模板與繼承

模板類的繼承與常規(guī)類的繼承非常相似。你可以定義一個(gè)模板類作為基類,然后創(chuàng)建另一個(gè)模板類或非模板類來繼承它。這種繼承允許派生類繼承基類的成員變量和成員函數(shù),同時(shí)還可以添加或覆蓋成員。
模板類繼承非模板類
首先,一個(gè)模板類可以繼承一個(gè)非模板類。這種情況下,模板類將繼承非模板類的所有成員。
如下為樣例代碼:

#include <iostream>  

class MyClassWithNonTemplate
{
public:
	void withoutTemplateFunc()
	{
		printf("function without template\n");
	}
};

template <typename T>
class MyClassWithTemplateDerived : public MyClassWithNonTemplate 
{
public:
	void withTemplateFunc()
	{
		printf("function with template for type : %s\n", typeid(T).name());
	}
};

int main() {
	MyClassWithTemplateDerived<int> obj;
	obj.withoutTemplateFunc(); // 調(diào)用繼承自非模板基類的成員函數(shù)  
	obj.withTemplateFunc();    // 調(diào)用模板派生類的成員函數(shù)  
	return 0;
}

上面代碼的輸出為:

function without template
function with template for type : int

模板類繼承模板類
更常見的是,一個(gè)模板類可以繼承另一個(gè)模板類。在這種情況下,派生類模板可以添加、覆蓋或使用基類模板的成員。
如下為樣例代碼:

#include <iostream>  

template <typename T>
class MyClassBase
{
public:
	void baseFunction()
	{
		printf("base type : %s\n", typeid(T).name());
	}
};

template <typename T1, typename T2=int>
class MyClassDerived : public MyClassBase<T2>
{
public:
	void derivedFunction()
	{
		printf("derived type : %s, base type : %s\n", typeid(T1).name(), typeid(T2).name());
	}
};

int main() {
	MyClassDerived<double> obj;
	obj.baseFunction();			// 調(diào)用模板基類的成員函數(shù)  
	obj.derivedFunction();		// 調(diào)用模板派生類的成員函數(shù)  
	return 0;
}

上面代碼的輸出為:

base type : int
derived type : double, base type : int

在這個(gè)例子中,MyClassDerived 繼承自 MyClassBase,并且 MyClassBase 是一個(gè)模板類。MyClassDerived 可以選擇性地提供模板參數(shù) T2,如果沒有提供,則默認(rèn)為 int。
注意事項(xiàng)
(1)模板參數(shù)傳遞:當(dāng)模板類繼承另一個(gè)模板類時(shí),可以選擇傳遞或省略模板參數(shù)。在上面的例子中,MyClassDerived 選擇了傳遞一個(gè)模板參數(shù) T1,并且為 T2 提供了一個(gè)默認(rèn)值 int。
(2)訪問控制:繼承的規(guī)則(公有繼承、保護(hù)繼承、私有繼承)同樣適用于模板類。公有繼承允許派生類訪問基類的公有和保護(hù)成員;保護(hù)繼承允許派生類訪問基類的公有和保護(hù)成員,但將這些成員視為保護(hù)成員;私有繼承允許派生類訪問基類的公有和保護(hù)成員,但將這些成員視為私有成員。
(3)特化和偏特化:當(dāng)涉及到模板類的繼承時(shí),特化和偏特化的規(guī)則同樣適用??梢詾榛惸0寤蚺缮惸0逄峁┨鼗蚱鼗姹尽?br> (4)虛函數(shù)和純虛函數(shù):如果基類模板包含虛函數(shù)或純虛函數(shù),派生類可以選擇覆蓋這些函數(shù)或提供自己的實(shí)現(xiàn)。這對(duì)于創(chuàng)建模板類和派生類的抽象基類尤其有用。文章來源地址http://www.zghlxwxcb.cn/news/detail-826913.html

到了這里,關(guān)于突破編程_C++_高級(jí)教程(模板編程的基礎(chǔ)知識(shí))的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 高級(jí)篇十三、事務(wù)基礎(chǔ)知識(shí)

    高級(jí)篇十三、事務(wù)基礎(chǔ)知識(shí)

    事務(wù)是數(shù)據(jù)庫(kù)區(qū)別文件系統(tǒng)的重要特性之一,當(dāng)我們有了事務(wù)會(huì)讓數(shù)據(jù)庫(kù)始終保持一致性,同時(shí)我們還能通過事務(wù)的機(jī)制恢復(fù)到某個(gè)時(shí)間點(diǎn),這樣可以保證已提交到數(shù)據(jù)庫(kù)的修改不會(huì)因?yàn)橄到y(tǒng)的崩潰而丟失! 1.1 存儲(chǔ)引擎支持情況 SHOW ENGINES 命令來查看當(dāng)前 MySQL 支持的存儲(chǔ)引

    2024年02月04日
    瀏覽(17)
  • 【C++】C++模板基礎(chǔ)知識(shí)篇

    【C++】C++模板基礎(chǔ)知識(shí)篇

    個(gè)人主頁(yè) : zxctscl 文章封面來自:藝術(shù)家–賢海林 如有轉(zhuǎn)載請(qǐng)先通知 實(shí)現(xiàn)一個(gè)通用的交換函數(shù): 在實(shí)現(xiàn)不同類型的參數(shù)Swap就得寫很多個(gè), 用起來太麻煩了。 使用函數(shù)重載雖然可以實(shí)現(xiàn),但是有一下幾個(gè)不好的地方: 重載的函數(shù)僅僅是類型不同,代碼復(fù)用率比較低,只要

    2024年03月28日
    瀏覽(21)
  • 快速上手MATLAB:科研、工程、數(shù)據(jù)分析,MATLAB入門(下)教你基礎(chǔ)知識(shí)!分享《MATLAB初學(xué)者教程 MATLAB編程-菜鳥入門(清晰版)》

    快速上手MATLAB:科研、工程、數(shù)據(jù)分析,MATLAB入門(下)教你基礎(chǔ)知識(shí)!分享《MATLAB初學(xué)者教程 MATLAB編程-菜鳥入門(清晰版)》

    1、《MATLAB完全學(xué)習(xí)手冊(cè)(視頻+課件+代碼)》 2、《MATLAB入門》 3、《詳解MATLAB在科學(xué)計(jì)算中的應(yīng)用》 4、《案例二 MATLAB與Excel交互》 5、《MATLAB初學(xué)者教程 MATLAB編程-菜鳥入門(清晰版)》 6、《MATLAB常用函數(shù)參考 MATLAB函數(shù)匯總 精通MATLAB》 7、等等。。。。 前兩天,我們?cè)冢?/p>

    2024年02月07日
    瀏覽(111)
  • 線性代數(shù)之美:從基礎(chǔ)知識(shí)到高級(jí)技巧

    線性代數(shù)是數(shù)學(xué)的一個(gè)分支,它研究的是線性方程組和線性空間等概念。線性代數(shù)在許多科學(xué)和工程領(lǐng)域都有廣泛的應(yīng)用,例如機(jī)器學(xué)習(xí)、計(jì)算機(jī)圖形學(xué)、信號(hào)處理等。在這篇文章中,我們將從基礎(chǔ)知識(shí)到高級(jí)技巧來詳細(xì)講解線性代數(shù)的核心概念、算法原理、具體操作步驟以

    2024年01月20日
    瀏覽(22)
  • 深入理解 C++ 語(yǔ)法:從基礎(chǔ)知識(shí)到高級(jí)應(yīng)用

    讓我們將以下代碼分解以更好地理解它: 示例 示例解釋 第 1 行: #include iostream 是一個(gè)頭文件庫(kù),它讓我們可以使用輸入和輸出對(duì)象,比如 cout (在第 5 行使用)。頭文件為 C++ 程序添加功能。 第 2 行: using namespace std 表示我們可以使用標(biāo)準(zhǔn)庫(kù)中的對(duì)象和變量名稱。 如果你

    2024年03月23日
    瀏覽(21)
  • 【Springboot】SpringBoot基礎(chǔ)知識(shí)及整合Thymeleaf模板引擎

    【Springboot】SpringBoot基礎(chǔ)知識(shí)及整合Thymeleaf模板引擎

    ??博客x主頁(yè):己不由心王道長(zhǎng)??! ??文章說明:spring?? ?系列專欄:spring ??本篇內(nèi)容:對(duì)SpringBoot進(jìn)行一個(gè)入門學(xué)習(xí)及對(duì)Thymeleaf模板引擎進(jìn)行整合(對(duì)所需知識(shí)點(diǎn)進(jìn)行選擇閱讀呀~)?? ??每日一語(yǔ):在人生的道路上,即使一切都失去了,只要一息尚存,你就沒有絲毫理

    2023年04月23日
    瀏覽(25)
  • 高級(jí)-UI-從零到整-(一)-View-的基礎(chǔ)知識(shí)你必須知道

    高級(jí)-UI-從零到整-(一)-View-的基礎(chǔ)知識(shí)你必須知道

    getX / getY : 返回相對(duì)于當(dāng)前 View 左上角的 x 和 y 的坐標(biāo) getRawX / getRawY : 返回的是相對(duì)于手機(jī)屏幕左上角的 x 和 y 坐標(biāo)。 TouchSlop TouchSlop 官方解釋就是系統(tǒng)所能識(shí)別的被認(rèn)為是滑動(dòng)的最小距離,通俗點(diǎn)說就是當(dāng)手指在屏幕上滑動(dòng)時(shí),如果兩次滑動(dòng)之間的距離小于這個(gè)常量,那么

    2024年04月26日
    瀏覽(25)
  • 并發(fā)編程的基礎(chǔ)知識(shí)

    并發(fā)編程的優(yōu)缺點(diǎn) 充分利用多核CPU的計(jì)算能力:通過并發(fā)編程的形式可以將多核CPU的計(jì)算能力發(fā)揮到極致,性能得到提升 方便進(jìn)行業(yè)務(wù)拆分,提升系統(tǒng)并發(fā)能力和性能:在特殊的業(yè)務(wù)場(chǎng)景下,先天的就適合于并發(fā)編程。現(xiàn)在的系統(tǒng)動(dòng)不動(dòng)就要求百萬(wàn)級(jí)甚至千萬(wàn)級(jí)的并發(fā)量,

    2024年02月06日
    瀏覽(23)
  • C++ 字符串完全指南:學(xué)習(xí)基礎(chǔ)知識(shí)到掌握高級(jí)應(yīng)用技巧

    字符串用于存儲(chǔ)文本。 一個(gè)字符串變量包含由雙引號(hào)括起來的一組字符: 示例 創(chuàng)建一個(gè) string 類型的變量并為其賦值: 字符串連接可以使用 + 運(yùn)算符來實(shí)現(xiàn),生成一個(gè)新的字符串。 示例: 在上面的示例中,我們?cè)?firstName 后面添加了一個(gè)空格,以便在輸出時(shí)在 \\\"John\\\" 和 \\\"D

    2024年04月08日
    瀏覽(34)
  • 網(wǎng)絡(luò)基礎(chǔ)知識(shí)&socket編程

    網(wǎng)絡(luò)基礎(chǔ)知識(shí)&socket編程

    Linux 系統(tǒng)是依靠互聯(lián)網(wǎng)平臺(tái)迅速發(fā)展起來的,所以它具有強(qiáng)大的網(wǎng)絡(luò)功能支持,也是Linux 系統(tǒng)的一大特點(diǎn)。互聯(lián)網(wǎng)對(duì)人類社會(huì)產(chǎn)生了巨大影響,它幾乎改變了人們生活的方方面面,可見互聯(lián)網(wǎng)對(duì)人類社會(huì)的重要性! 本章我們便來學(xué)習(xí)一些網(wǎng)絡(luò)基礎(chǔ)知識(shí),如果感興趣的讀者可以

    2024年02月10日
    瀏覽(23)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包