C++類模板在不同情況下的使用


類模板和函數模板的定義和使用類似。
有時,有兩個或多個類,其功能是相同的,僅僅是數據類型不同。

1. 類模板用於實現類所需數據的類型參數化

類模板可以有默認參數,比如:

template<typename NameType, typename AgeType=int>

而函數模板不支持有默認參數
類模板不能進行類型自動推導

template<typename NameType, typename AgeType>
class Person{
public:
	Person(NameType name, AgeType age){
		this->mName = name;
		this->mAge = age;
	}
	void showPerson(){
		cout << "name: " << this->mName << " age: " << this->mAge << endl;
	}
public:
	NameType mName;
	AgeType mAge;
};

void test01(){
	//Person P1("小明",18); // 類模板不能進行類型自動推導 
	Person<string, int>P1("小明", 18);
	P1.showPerson();
}

2. 類模板中成員函數 一開始不會創建出來,而是在運行時纔去創建

class Person1{
public:
	void showPerson1(){
		cout << "Person1的調用" << endl;
	}
};
class Person2{
public:
	void showPerson2(){
		cout << "Person2的調用" << endl;
	}
};

template<typename T>
class myClass{
public:
	T obj;
	void func1(){
		obj.showPerson1();
	}
	void func2(){
		obj.showPerson2();
	}
};
//類模板中成員函數 一開始不會創建出來,而是在運行時纔去創建
void test01(){
	myClass<Person1>m;
	m.func1();
	//m.func2();//連着上一條語句編譯會不通過,因爲已經確定好了T類型爲Person1之後,執行obj.showPerson2();的時候會提示沒有此函數
}

3. 類模板做函數參數

3.1 指定傳輸類型

//類模板
template<typename NameType, typename AgeType>
class Person{
public:
	Person(NameType name, AgeType age){
		this->mName = name;
		this->mAge = age;
	}
	void PrintPerson(){
		cout << "Name:" << this->mName << " Age:" << this->mAge << endl;
	}
public:
	NameType mName;
	AgeType mAge;
};

//類模板做函數參數
void DoBussiness(Person<string,int>& p){//指定傳輸類型
	p.mAge += 20;
	p.mName += "_vip";
	p.PrintPerson();
}

int main(){
	Person<string, int> p("John", 30);
	DoBussiness(p);
	return EXIT_SUCCESS;
}

3.2 參數模板化

函數模板內套類模板,用函數模板的可以自動推導類型的特點
查看類型名稱: typeid(T).name()

//類模板
template<typename NameType, typename AgeType>
class Person{
public:
	Person(NameType name, AgeType age){
		this->mName = name;
		this->mAge = age;
	}
	void PrintPerson(){
		cout << "Name:" << this->mName << " Age:" << this->mAge << endl;
	}
public:
	NameType mName;
	AgeType mAge;
};

template<typename T1 ,typename T2>
void doWork2(Person<T1, T2> & p){//函數模板內套類模板,用函數模板的可以自動推導類型的特點
	//如何查看類型
	cout << typeid(T1).name() << endl;
	cout << typeid(T2).name() << endl;
	p.showPerson();
}
void test02(){
	Person <string, int> p("小明", 18);
	doWork2(p);
}

3.3 整體模板化

把整體類型模板化,讓函數模板自動推導

template<typename T>
void doWork3(T&p){//把整體類型模板化,自動推導
	cout << typeid(T).name() << endl;
	p.showPerson();
}

void test03(){
	Person <string, int> p("小王", 18);

	doWork3(p);
}

4. 類模板派生普通類

子類實例化的時候需要具體化父類的類型,子類需要知道父類的具體類型是什麼樣的,這樣c++編譯器才能知道給子類分配多少內存

//父類類模板
template<typename T>
class Base{
	T m;
};
class Child1 : public Base<double> { //繼承類模板的時候,必須要確定基類的大小
};

void test02(){
	Child1 d1;
}

5. 類模板派生類模板

繼承類模板的時候,必須要確定基類的大小

//父類類模板
template<typename T>
class Base{
	T m;
};
template<typename T1 ,typename T2>
class Child2 : public Base<T2> { //繼承類模板的時候,必須要確定基類的大小
public:
	T1 mParam;
};

void test02(){
	Child2<int,double> d2;//int mParam; double m;
}

6. 類模板類內實現

類內實現就是上面寫的普通的類模板

template<typename NameType, typename AgeType>
class Person{
public:
	Person(NameType name, AgeType age){
		this->mName = name;
		this->mAge = age;
	}
	void showPerson(){
		cout << "name: " << this->mName << " age: " << this->mAge << endl;
	}
public:
	NameType mName;
	AgeType mAge;
};

void test01(){
	//Person P1("小明",18); // 類模板不能進行類型自動推導 
	Person<string, int>P1("小明", 18);
	P1.showPerson();
}

7. 類模板類外實現

類模板的類外實現是爲了方便分文件,但是一般我們寫了類模板之後不要進行分文件編寫,寫到同一個文件中,進行聲明和實現,後綴名改爲.hpp

#include<iostream>
#include<string>
using namespace std;

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

public:
	T1 mName;
	T2 mAge;
};

//類外實現
template<typename T1, typename T2>
Person<T1, T2>::Person(T1 name, T2 age){
	this->mName = name;
	this->mAge = age;
}

template<typename T1, typename T2>
void Person<T1, T2>::showPerson(){
	cout << "Name:" << this->mName << " Age:" << this->mAge << endl;
}

void test(){
	Person<string, int> p("小明", 18);
	p.showPerson();
}

int main(){
	test();
	return EXIT_SUCCESS;
}

8. 模板類碰到友元函數

#include<iostream>
using namespace std;
#include <string>

//告訴編譯器這個函數模板是存在的同時也要告訴編譯器這個函數模板中用的類也是存在的
template<typename T1, typename T2> 
class Person;
//告訴編譯器這個函數模板是存在
template<typename T1, typename T2> 
void PrintPerson2(Person<T1, T2>& p);

//友元函數在類內實現
template<typename T1, typename T2>
class Person{
	//1. 友元函數在類內實現
	friend void PrintPerson(Person<T1, T2>& p){
		cout << "Name:" << p.mName << " Age:" << p.mAge << endl;
	}

	//2.友元函數類外實現
	//告訴編譯器這個函數模板是存在
	friend void PrintPerson2<>(Person<T1, T2>& p);//<>表示這是個模板

	//3. 類模板碰到友元函數模板
	template<typename U1, typename U2>
	friend void PrintPerson(Person<U1, U2>& p);

public:
	Person(T1 name, T2 age){
		this->mName = name;
		this->mAge = age;
	}
	void showPerson(){
		cout << "Name:" << this->mName << " Age:" << this->mAge << endl;
	}
private:
	T1 mName;
	T2 mAge;
};

void test01(){
	Person <string, int>p("Jerry", 20);
	PrintPerson(p);
}

// 類模板碰到友元函數
//友元函數類外實現  加上<>空參數列表,告訴編譯去匹配函數模板
template<typename T1, typename T2>
void PrintPerson2(Person<T1, T2>& p){
	cout << "Name2:" << p.mName << " Age2:" << p.mAge << endl;
}

void  test02(){
	Person <string, int>p("Jerry", 20);
	PrintPerson2(p);   //不寫可以編譯通過,寫了之後,會找PrintPerson2的普通函數調用,因爲寫了普通函數PrintPerson2的聲明	
}

int main(){
	//test01();
	test02();
	return EXIT_SUCCESS;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章