日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

C++初階學習之模板進階_C 語言

作者:可口也可樂、 ? 更新時間: 2022-03-29 編程語言

一、非模板類型參數

分類:

模板參數分類類型形參與非類型形參

概念:

1.類型形參:

出現在模板參數列表中,跟在class或者typename之類的參數類型名稱

2.非類型形參:

用一個常量作為類(函數)模板的一個參數,在類(函數)模板中可將該參數當成常量來使用

示例:

namespace cole
{
	// 定義一個模板類型的靜態數組
	template<class T, size_t N = 10>
	class array
	{
	public:
		T& operator[](size_t index) 
		{ 
			return _array[index]; 
		}

		const T& operator[](size_t index)const 
		{ 
			return _array[index]; 
		}

		size_t size()const 
		{ 
			return _size; 
		}

		bool empty()const 
		{ 
			return 0 == _size; 
		}
	private:
		T _array[N];
		size_t _size;
	};
}

注意:

1.浮點數、類對象以及字符串是不允許作為非類型模板參數的

2.非類型的模板參數必須在編譯期就能確認結果

二、模板特化

概念:

使用模板可以實現一些與類型無關的代碼,但對于一些特殊類型的可能會得到一些錯誤的結果

示例:

template<class T>
bool IsEqual(const T& left, const T& right)
{
	return left == right;
}
// 函數模板的特化 (針對某些類型的特殊化處理)
//bool IsEqual(const char* const & left,const char* const & right)
bool IsEqual(const char* left, const char* right)
{
	return strcmp(left, right) == 0;
}
int main()
{
	cout << IsEqual(1, 2) << endl;
	char p1[] = "hello";
	char p2[] = "hello";
	cout << IsEqual(p1, p2) << endl;;
	return 0;
}

特殊化結果:

?

image-20220102174246490

?不做特殊化結果:

?image-20220102174324473

注:此時對于字符串比較就需要對模板進行特化(在原模板類的基礎上,針對特殊類型所進行特殊化的實現方式)

特化分類:

函數模板特化類模板特化

1、函數模板特化

函數模板的特化步驟:

  • 必須要先有一個基礎的函數模板
  • 關鍵字template后面接一對空的尖括號<>
  • 函數名后跟一對尖括號,尖括號中指定需要特化的類型
  • 函數形參表: 必須要和模板函數的基礎參數類型完全相同,如果不同編譯器可能會報一些奇怪的錯誤

示例:

template<class T>
bool IsEqual(const T left, const T right)
{
	return left == right;
}
template<>
bool IsEqual<char*>(char* left,char* right)
{
	if (strcmp(left, right) == 0)
		return true;
	return false;
}

結果:

?image-20220102175925378

注:一般情況下如果函數模板遇到不能處理或者處理有誤的類型,為了實現簡單通常都是將該函數直接給出

示例:

bool IsEqual(char* left, char* right)
{
	if (strcmp(left, right) == 0)
		return true;
	return false;
}

2、類模板特化

1)全特化

概念:

全特化即是將模板參數列表中所有的參數都確定化

示例:

template<class T1, class T2>
class Data
{
public:
	Data() { cout << "Data<T1, T2>" << endl; }
private:
	T1 _d1;
	T2 _d2;
};
template<>
class Data<int, char>
{
public:
	Data() { cout << "Data<int, char>" << endl; }
private:
	int _d1;
	char _d2;
};
void TestVector()
{
	Data<int, int> d1;
	Data<int, char> d2;
}

2)偏特化

概念:

任何針對模版參數進一步進行條件限制設計的特化版本

偏特化有以下兩種表現方式:

1.部分特化

將模板參數類表中的一部分參數特化

示例:

// 將第二個參數特化為inttemplate <class T1>class Data<T1, int>{public:Data() { cout << "Data<T1, int>" << endl; }private:T1 _d1;int _d2;};// 將第二個參數特化為int
template <class T1>
class Data<T1, int>
{
public:
	Data() { cout << "Data<T1, int>" << endl; }
private:
	T1 _d1;
	int _d2;
};

2.參數更進一步的限制

偏特化并不僅僅是指特化部分參數,而是針對模板參數更進一步的條件限制所設計出來的一個特化版本

示例:

//兩個參數偏特化為指針類型template <typename T1, typename T2>class Data <T1*, T2*>{public:Data() { cout << "Data<T1*, T2*>" << endl; }private:T1 _d1;T2 _d2;};//兩個參數偏特化為引用類型template <typename T1, typename T2>class Data <T1&, T2&>{public:Data(const T1& d1, const T2& d2): _d1(d1), _d2(d2){cout << "Data<T1&, T2&>" << endl;}private:const T1& _d1;const T2& _d2;};void test2(){Data<double, int> d1; // 調用特化的int版本Data<int, double> d2; // 調用基礎的模板Data<int*, int*> d3; // 調用特化的指針版本Data<int&, int&> d4(1, 2); // 調用特化的指針版本}//兩個參數偏特化為指針類型
template <typename T1, typename T2>
class Data <T1*, T2*>
{
public:
	Data() { cout << "Data<T1*, T2*>" << endl; }
private:
	T1 _d1;
	T2 _d2;
};
//兩個參數偏特化為引用類型
template <typename T1, typename T2>
class Data <T1&, T2&>
{
public:
	Data(const T1& d1, const T2& d2)
		: _d1(d1)
		, _d2(d2)
	{
		cout << "Data<T1&, T2&>" << endl;
	}
private:
	const T1& _d1;
	const T2& _d2;
};
void test2()
{
	Data<double, int> d1; // 調用特化的int版本
	Data<int, double> d2; // 調用基礎的模板
	Data<int*, int*> d3; // 調用特化的指針版本
	Data<int&, int&> d4(1, 2); // 調用特化的指針版本
}

三、模板分離編譯

分離編譯概念:

一個程序(項目)由若干個源文件共同實現,而每個源文件單獨編譯生成目標文件,最后將所有目標文件鏈接起來形成單一的可執行文件的過程稱為分離編譯模式

模板分離編譯:

假如有以下場景,模板的聲明與定義分離開,在頭文件中進行聲明,源文件中完成定義

示例:

// a.h
template<class T>
T Add(const T& left, const T& right);
// a.cpp
template<class T>
T Add(const T& left, const T& right)
{
	return left + right;
}
// main.cpp
#include"a.h"
int main()
{
	Add(1, 2);
	Add(1.0, 2.0);
	return 0;
}

注:以上代碼的模板分離編譯會報錯

分析:?

image-20220102180953843

解決方法

1.將聲明和定義放到一個文件?“xxx.hpp”?(h文件和cpp文件結合)里面或者xxx.h其實也是可以的(推薦)

2.模板定義的位置顯式實例化(不實用)

四、模板總結

優點:

  • 模板復用了代碼,節省資源,更快的迭代開發,C++的標準模板庫(STL)因此而產生
  • 增強了代碼的靈活性

缺陷:

  • 模板會導致代碼膨脹問題,也會導致編譯時間變長(為了盡量減少此類問題,編譯器會按需實例化)
  • 出現模板編譯錯誤時,錯誤信息非常凌亂,不易定位錯誤
  • 不支持分離編譯

總結

原文鏈接:https://blog.csdn.net/CS_z_jun/article/details/122489790

欄目分類
最近更新