59 C++ - 類模板

1. 類模板基本概念

類模板和函數模板的定義和使用相似,咱們已經進行了介紹。有時,有兩個或多個類,其功能是相同的,僅僅是數據類型不一樣。ios

類模板用於實現類所需數據的類型參數化c++

template<class NameType, class 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. 類模板作函數參數

//類模板
template<class NameType, class 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);

	system("pause");
	return EXIT_SUCCESS;
}

3. 類模板派生普通類

//類模板
template<class T>
class MyClass{
public:
	MyClass(T property){
		this->mProperty = property;
	}
public:
	T mProperty;
};

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

//普通派生類
class SubClass : public MyClass<int>{
public:
	SubClass(int b) : MyClass<int>(20){
		this->mB = b;
	}
public:
	int mB;
};

4. 類模板派生類模板

//父類類模板
template<class T>
class Base
{
	T m;
};
template<class T >
class Child2 : public Base<double>  //繼承類模板的時候,必需要肯定基類的大小
{
public:
	T mParam;
};

void test02()
{
	Child2<int> d2;
}

5. 類模板類內實現

template<class NameType, class 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();
}

6. 類模板類外實現

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

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

public:
	T1 mName;
	T2 mAge;
};


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


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

void test()
{
	Person<string, int> p("Obama", 20);
	p.showPerson();
}

int main(){

	test();

	system("pause");
	return EXIT_SUCCESS;
}

7. 類模板頭文件和源文件分離問題

Person.hpp編輯器

#pragma once

template<class T1,class T2>
class Person{
public:
	Person(T1 name,T2 age);
	void ShowPerson();
public:
	T1 mName;
	T2 mAge;
};

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

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

main.cppide

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include<string>
#include"Person.hpp"

//模板二次編譯
//編譯器編譯源碼 逐個編譯單元編譯的

int main(){

	Person<string, int> p("Obama", 20);
	p.ShowPerson();


	system("pause");
	return EXIT_SUCCESS;
}

結論: 案例代碼在qt編譯器順利經過編譯並執行,可是在Linux和vs編輯器下若是隻包含頭文件,那麼會報錯連接錯誤,須要包含cpp文件,可是若是類模板中有友元類,那麼編譯失敗!函數

解決方案: 類模板的聲明和實現放到一個文件中,咱們把這個文件命名爲.hpp(這個是個約定的規則,並非標準,必須這麼寫).this

緣由:spa

  • 類模板須要二次編譯,在出現模板的地方編譯一次,在調用模板的地方再次編譯。
  • C++編譯規則爲獨立編譯。

8. 模板類碰到友元函數

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

template<class T1, class T2> class Person;
//告訴編譯器這個函數模板是存在
template<class T1, class T2> void PrintPerson2(Person<T1, T2>& p);

//友元函數在類內實現
template<class T1, class 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<class U1, class 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<class T1 , class 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();
	system("pause");
	return EXIT_SUCCESS;
}
相關文章
相關標籤/搜索