【C++進階筆記】(1)函式模板的宣告及使用

CielleeX發表於2020-10-05

最近在搞FFmpeg 音視訊開發,後面大量涉及音視訊圖形等介面開發(比如視訊播放器),
利用C語言也可以實現 ,但相對麻煩,在這方面C++會方便很多,記得上一次學C++還是在大二的時候了,
剛好也算趁著這一次機會,把C++ 的知識全部重新撿起來鞏固一遍,
也算逼自已一把,實現由C轉C++,後面寫程式碼、寫演算法就全使用C++ 來實現了。

有關C++ 的學習,打算專門花兩天時間全部過一遍,因為有基礎,所以我學習時都是跳著學,這樣快些
參考視訊教程:《C++教程從0到1入門程式設計

  • 第一天 10月4號
    將C++基礎全部過了一遍 (物件導向),
    包括C++中的資料型別、陣列、指標、類和物件等,和C大同小異,這裡就不多說了。

  • 第二天 10月5號
    將C++更高階一些程式設計過一遍(泛型程式設計思想),這些功能很多都是C中沒有的,用起來確實會很方便。

好了,前言就到這裡吧,我們開始學習。


一、函式模板 template < class T>

有關知識點 ,我全部以註釋的形式寫在程式碼中,結合程式碼方便理解運用


1. 簡單的函式模板示例

  • 函式模板宣告:
    template <typename T>,T 是一個通用資料型別,將資料型別引數化,利高程式碼的複用性
    typename 也可以寫成 template<class T>,沒什麼差別

  • 函式模板使用有兩種方法:
    (1)方法一:利用編譯器自動推導(必須推匯出一致的資料型別 T 才可以使用)
    (2)方法二:顯示指定型別 T,在顯示指定型別後,轉參如果不是當前型別,則會自動發生隱式型別轉換。

示例如下:

#include <iostream>
using namespace std;

// 宣告一個函式模板,告訴編譯器後面程式碼中緊跟著的T不要的報錯
// T 是一個通用資料型別,將資料型別引數化,利高程式碼的複用性
template<typename T>	

// 交換兩個資料,資料型別為 T,資料傳遞方式為引用
void Swap(T &a, T &b){
	T temp = a;
	a = b;
	b = temp;
}

int main(){
	int a = 10, b = 20;
	cout << "初始值: a = " << a << " b = " << b << endl;

	// 利用函式模板交換資料

	// 方法一:利用編譯器自動推導
	cout << "方法一、利用編譯器自動推導 T 的資料型別" << endl;
	Swap(a, b);
	cout << "交換後: a = " << a << " b = " << b << endl << endl;

	// 方法二:顯示指定型別 T
	cout << "方法二 、顯示指定型別 T" << endl;
	Swap<int>(a, b);	// 指定T 的資料型別為 T
	cout << "交換後: a = " << a << " b = " << b << endl;

	system("pause"); 
	return 0;
}


2. 實現通用資料型別排序演算法示例

#include <iostream>
using namespace std;

// 實現通用的對陣列從小到大排序的函式
template <class T>
void Sort_array(T arr[], int len)
{	
	// 選擇排序
	for (int i = 0; i < len; i++){			// 外迴圈
		int max = i;
		for (int j = i + 1; j < len; j++)	// 內迴圈
		{
			if (arr[max] >  arr[j]) {		// 比較出最小值索引
				max = j;
			}
		}
		if (max != i) {		// 交換元素
			T temp = arr[i];
			arr[i] = arr[max];
			arr[max] = temp; 
		}
	}
}

template<class T>
void print_array(T arr[], int  len){
	for (int i = 0; i < len; i++){
		cout << arr[i] << " ";
	}
	cout << endl << endl;
}

int main()
{
	{
		char c_arr[] = "zyxwvutsrqponmlkjihgfedcba";
		int num = sizeof(c_arr) / sizeof(char) - 1;

		// 對陣列進行從小到大排序
		Sort_array(c_arr, num);
		print_array(c_arr, num);	// 列印陣列 
	}
	{
		float f_arr[] = { 10.1,9.1,8.1,7.1,6.1,5.1,4.1,3.1,2.1,1.1 };
		int num = sizeof(f_arr) / sizeof(float);

		// 對陣列進行從小到大排序
		Sort_array(f_arr, num);
		print_array(f_arr, num);	// 列印陣列 
	}

	system("pause"); 
	return 0;
}

3. 能過空模板引數列表 強制呼叫模板函式

當普通函式,與 模板函式重名時,如果要強制呼叫模板函式,需要使用增加空模板引數列表來實現:Sort_array<>(c_arr, num);

程式碼示例如下,
如果不使用Sort_array<>(c_arr, num);來呼叫,
預設會呼叫普通函式Sort_array,從而報程式錯誤(函式未實現),
使用空模板引數列表後,正常執行,呼叫的是模板函式。


#include <iostream>
using namespace std;

void Sort_array(char arr[], int len);

// 實現通用的對陣列從小到大排序的函式
template <class T>
void Sort_array(T arr[], int len)
{	
	// 選擇排序
	for (int i = 0; i < len; i++)			// 外迴圈
	{
		int max = i;
		for (int j = i + 1; j < len; j++)	// 內迴圈
		{
			if (arr[max] >  arr[j]) {		// 比較出最小值索引
				max = j;
			}
		}
		if (max != i) {		// 交換元素
			T temp = arr[i];
			arr[i] = arr[max];
			arr[max] = temp; 
		}
	}
}

template<class T>
void print_array(T arr[], int  len)
{
	for (int i = 0; i < len; i++)
	{
		cout << arr[i] << " ";
	}
	cout << endl << endl;
}

int main()
{
	{
		char c_arr[] = "zyxwvutsrqponmlkjihgfedcba";
		int num = sizeof(c_arr) / sizeof(char) - 1;

		// 對陣列進行從小到大排序
		Sort_array<>(c_arr, num);
		print_array(c_arr, num);	// 列印陣列 
	}
	{
		float f_arr[] = { 10.1,9.1,8.1,7.1,6.1,5.1,4.1,3.1,2.1,1.1 };
		int num = sizeof(f_arr) / sizeof(float);

		// 對陣列進行從小到大排序
		Sort_array<>(f_arr, num);
		print_array(f_arr, num);	// 列印陣列 
	}

	system("pause"); 
	return 0;
}

4. 模板函式 也可 以實現函式過載

示例如下:

template <class T>
void fun(T &a, T &b ){  XXX; }

template <class T>
void fun(T &a, T &b , T &c){  XXX; }

template <class T>
void fun(T &a, T &b , T &c,  int d){  XXX; }

相關文章