C++編程提高——模板

C++編程提高——模板

一、模板的概念

模板就是建立通用的模具,打打提高複用性

模板的特點:

  • 模板不可以直接使用,它只是一個框架
  • 模板的通用並不是萬能的

二、函數模板

  • C++另一種編程思想稱爲泛型編程,主要利用的技術就是模板
  • C++提供兩種模板機制:函數模板類模板

2.1函數模板語法

函數模板的作用:

建立一個通用函數,其函數返回值類型和形參類型可以不具體指定,用一個虛擬的類型來代表

語法:

template<typename T>
函數聲明或定義

解釋:

template:聲明創建模板

typename:表面其後面的符號是一種數據類型,可以用class代替

T:通用的數據類型,名稱可以替換,通常爲大寫字母

示例:

template<typename T>
void mySwap(T& a, T& b) {
	T temp = a;
	a = b;
	b = temp;
}

void test11() {
	int a = 10;
	int b = 20;
	//自動類型推導
	//mySwap(a, b);
	//設置類型
	mySwap<int>(a, b);
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
}

2.2函數模板注意事項

注意事項:

  • 自動類型推導,必須推導出一致的數據類型T,纔可以使用
  • 模板必須要確定出T的數據類型,纔可以使用

2.3普通函數與函數模板的區別

  • 普通函數調用時可以發生自動類型轉換(隱式類型轉換)
  • 函數模板調用時,如果利用自動類型推導,不會發生隱式類型轉換
  • 如果利用顯示指定類型的方式,可以發生隱式類型轉換

2.4普通函數與函數模板的調用規則

如下:

  • 如果函數模板和普通函數都可以實現,優先調用普通函數
  • 可以通過空模板參數列表來強制調用函數模板
  • 函數模板也可以發生重載
  • 如果函數模板可以產生更好的匹配,優先調用函數模板

三、類模板

3.1類模板語法

作用:建立一個通用類,類中的成員數據類型可以不具體制定,用一個虛擬的類型代表。

語法:

template<typename T>
類

解釋:

  • template:聲明創建模板
  • typename:表面其後面的符號是一種數據類型,可以用class代替
  • T:通用的數據類型,名稱可以替換,通常爲大寫字母

示例:

#include<iostream>
using namespace std;

template<class nameType, class ageType>
class Person {
public:
	Person(nameType name, ageType age) {
		this->name = name;
		this->age = age;
	}

	void showInfo() {
		cout << "name = " << this->name << endl;
		cout << "age = " << this->age << endl;
	}

	nameType name;
	ageType age;
};

int main() {

	Person<string, int> p1("張三", 20);
	p1.showInfo();

	/*
		name = 張三
		age = 20
	*/

	system("pause");
	return 0;
}

3.2類模板與函數模板的區別

  • 類模板沒有自動推導的使用方式
  • 類模板在模板參數列表中可以有默認參數
template<class nameType, class ageType = int>

3.3類模板中成員函數創建時機

  • 普通類中的成員函數在一開始就可以創建
  • 類模板中的成員函數在調用時才創建

3.4類模板對象做函數參數

一共有三種傳入方式:

  • 指定傳入的類型:直接顯示對象的數據類型
  • 參數模板化:將對象中的參數變爲模板進行傳遞
  • 整個類模板化:將這個對象類型模板化進行傳遞

示例:

#include<iostream>
using namespace std;

template<class T1, class T2>
class Person {
public:
	Person(T1 name, T2 age) {
		this->name = name;
		this->age = age;
	}

	void showInfo() {
		cout << "name = " << this->name << endl;
		cout << "age = " << this->age << endl;
	}

	T1 name;
	T2 age;
};

//使用直接指定類型
void testT31(Person<string, int> p) {
	p.showInfo();
}

void test31() {
	Person<string, int> p("Tom", 20);
	testT31(p);
}

//將參數模板化
template<class T1, class T2>
void testT32(Person<T1, T2> p) {
	p.showInfo();
}

void test32() {
	Person<string, int> p("Jack", 18);
	testT32(p);
}

//將整個類模板化
template<class T>
void testT33(T p) {
	p.showInfo();
}

void test33() {
	Person<string, int> p("Rose", 30);
	testT33(p);
}

int main() {

	test31();
	test32();
	test33();

	/*
		name = Tom
		age = 20
		name = Jack
		age = 18
		name = Rose
		age = 30
	*/

	system("pause");
	return 0;
}

3.5類模板與繼承

注意:

  • 當子類繼承的父類是一個模板類時,子類在聲明時要指定出父類中T的類型
  • 如果不指定,編譯器無法給子類分配內存
  • 如果想靈活的指定出父類中T的類型,子類也需要變爲類模板

3.6成員函數類外實現

示例:

template<class T1, class T2>
class Person {
public:
	Person(T1 name, T2 age);

	void showInfo();

	T1 name;
	T2 age;
};

template<class T1, class T2>
Person<T1, T2>::Person(T1 name, T2 age) {
	this->name = name;
	this->age = age;
}

template<class T1, class T2>
void Person<T1, T2>::showInfo() {
	cout << "name = " << this->name << endl;
	cout << "age = " << this->age << endl;
}

3.7類模板分文件編寫

問題:

  • 類模板中成員函數創建時機是在調用階段,導致分文件編寫時鏈接不到

解決:

  • 直接包含.cpp文件
  • 將聲明和實現寫到同一個文件中,並後綴名改爲.hpp,此名稱爲約定的名稱,並不是強制

3.8類模板與友元

全局函數類內實現:直接在類內聲明友元即可

全局函數類外實現:需要提前讓編譯器知道全局函數的存在

示例:

#include<iostream>
using namespace std;

//需要讓編譯器知道Person的存在
template<class T1, class T2>
class Person;

//類外實現友元
template<class T1, class T2>
void getPersonMsg2(Person<T1, T2> p) {
	cout << "name = " << p.name << " age = " << p.age << endl;
}

template<class T1, class T2>
class Person {

	//類內實現友元
	friend void getPersonMsg(Person<T1, T2> p) {
		cout << "name = " << p.name << " age = " << p.age << endl;
	}

	//類外實現需要添加空模板參數列表
	friend void getPersonMsg2<>(Person<T1, T2> p);

public:
	Person(T1 name, T2 age) {
		this->name = name;
		this->age = age;
	}

private:
	T1 name;
	T2 age;
};

int main() {
	Person<string, int> p("tom", 20);
	getPersonMsg(p);
	getPersonMsg2(p);

	system("pause");
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章