模板類的實現語法

一、定義一個模板類聲明

template<typename T1, typename T2>
class Complex;

template<typename T1, typename T2>
Complex<T1, T2> MySub(Complex<T1, T2> a, Complex<T1, T2> b);

template<typename T1,typename T2>
class Complex
{
	friend Complex MySub<T1,T2>(Complex a, Complex b);
	friend ostream& operator<< <T1, T2>(ostream &out, const Complex&c1);
	
public:
	Complex(T1 a, T2 b);
	Complex& operator+( Complex& c1);

private:
	T2 b;
	T1 a;
};
在上面的生命中有四種函數,分別是:

1.模板類Complex的成員函數;2.普通操作符重載;3.友元操作符重載函數;4.友元非操作符重載函數。

對於上面這4種類型的函數,模板類的函數實現分別是這樣實現的:


1.模板類Complex的成員函數;

Complex(T1 a, T2 b);
函數在類的外部實現代碼

template <typename T1, typename T2>
Complex<T1, T2>::Complex(T1 a, T2 b)
{
	this->a = a;
	this->b = b;
}


2.普通操作符重載:

Complex& operator+( Complex& c1);
函數在類的外部實現代碼:

template <typename T1,typename T2>
Complex<T1,T2>& Complex<T1, T2>::operator+( Complex& c1)
{
	this->a = this->a + c1.a;
	this->b = this->b + c1.b;
	return *this;
}


3.友元操作符重載函數

friend ostream& operator<< <T1, T2>(ostream &out, const Complex&c1);

函數在類的外部實現代碼:

template<typename T1,typename T2>
ostream& operator<<(ostream &out, const Complex<T1,T2>&c1)
{
	out << "a=" << c1.a << ":b=" << c1.b << endl;
	return out;
}
注意:通過觀察模板類的友元函數的定義,我們可以觀察到,在函數名的後面添加了<T1,T2>,爲什麼要添加<T1,T2>呢?我的理解是:根據友元函數本身的性質,友元函數的本質是全局函數,只不過是在類的內部聲明罷了,賦予友元函數可以訪問類內部的私有成員和保護成員的功能,那麼在函數聲明時,在函數名的後面添加上<T1,T2>,便於實例化模板類時要將具體的類型傳給友元函數。




4.友元非操作符重載函數

friend Complex MySub<T1,T2>(Complex a, Complex b);

程序在類外部的實現代碼

<pre name="code" class="cpp">template<typename T1, typename T2>	//類的前置定義
class Complex;
template<typename T1, typename T2>	//函數的前置定義
Complex<T1, T2> MySub(Complex<T1, T2> a, Complex<T1, T2> b);
template<typename T1,typename T2>
Complex<T1, T2> MySub(Complex<T1, T2> a, Complex<T1, T2> b)
{
	Complex<T1,T2> tmp(a.a - b.a, a.b - b.b);
	return tmp;
}





注意:在類的外部實現友元非操作符重載函數時,需要在函數前面重新:寫類的前置定義和函數的前置定義,當然了由於是友元函數,所以

在模板類內部聲明函數時,也需要在函數名後面,添加上類型<T1,T2>,便於實例化模板類時,將類型傳遞給友元函數。

【編譯器關於模板類的實現機制】

模板方法和模板類和普通的函數相比有兩步初始化的過程:1.類型初始化,2.參數初始化。

在分離式編譯的環境下,編譯器編譯某一個.cpp文件時並不知道另一個.cpp文件的存在,也不會去查找(當遇到未決符號時它會寄希望於連接器)。這種模式在沒有模板的情況下運行良好,但遇到模板時就傻眼了,因爲模板僅在需要的時候纔會實例化出來,所以,當編譯器只看到模板的聲明時,它不能實例化該模板,只能創建一個具有外部連接的符號並期待連接器能夠將符號的地址決議出來。然而當實現該模板的.cpp文件中沒有用到模板的實例時,編譯器懶得去實例化,所以,整個工程的.obj中就找不到一行模板實例的二進制代碼,於是連接器也黔驢技窮了。

所以在寫模板類是最好將模板函數的實現和聲明寫到同一個文件中(*.hpp)



發佈了11 篇原創文章 · 獲贊 9 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章