1. 程式人生 > >模板初步——定義模板

模板初步——定義模板

main strong 函數類 unsigned ati 顯式 make 類模板 友元

一、關鍵點

定義函數模板&類模板

模板參數列表:非類型參數

類模板類名的使用:依據作用域是否加上模板類型

類模板和友元:設置友好關系

模板參數:使用類的類型成員、默認模板實參

成員模板的使用:非模板類的成員模板、模板類的成員模板

二、定義函數模板

//模板參數T是一個類型 
template <typename T>
bool cmp(const T &a, const T &b)
{
	return a < b;
} 
//模板參數N是一個非類型參數 
template <unsigned N>
void get_val(int (&arr)[N])
{
	for (const auto &v : arr)
		cout << v << " ";
}

註:一個非類型參數可以一個整型,或者是一個指向對象或函數類型的指針或(左值)引用。

註:綁定到非類型整型參數的實參必須是一個常量表達式(從而允許編譯器在編譯時實例化模板)。

三、定義類模板

template <typename T>
class Blob
{
public:
	using size_type = typename vector<T>::size_type;
	//...
} 

int main()
{	
	Blob<int> b;
    return 0;
}

  

四、類模板的成員函數

template <typename T>
class Blob
{
public:
	using size_type = typename vector<T>::size_type;
	//...
private:
	void check(size_type i, const string &s) const;
};
//成員函數類外定義
template <typename T>
void Blob<T>::check(size_type i, const string &msg) const
{
	//...
}

註:定義在類模板內的成員函數被隱式聲明為內聯函數。

註:一個類模板的成員函數只有在使用時才被實例化。

五、類模板的友元

友元是模板:類可以授權給所有友元模板實例,也可以只授權給特定實例

友元不是模板:友元被授權可以訪問所有模板實例

1. 一對一友好關系(友元是模板,且友元的模板類型與類模板的一致)

//Blob的友元是模板函數operator==和模板類BlobPtr 
template <typename> class Blob;	//該聲明是operator==函數的參數聲明所需要的 
template <typename T> bool operator==(const Blob<T>&, const Blob<T>&);
template <typename> class BlobPtr;	//該聲明是Blob中的友元聲明所需要的 

template <typename T>
class Blob
{
	//每個Blob實例將訪問權限授予用相同類型實例化的BlobPtr和相等運算符 
	friend class BlobPtr<T>;
	friend bool operator==(const Blob<T>&, const Blob<T>&);
	//...
};
template <typename T> class pal;
template <typename T> class C { //C的每個實例將相同實例化的pal聲明為友元 friend class pal<T>; }
template <typename T> class pal;

class C {
	//用類C實例化的pal是C的一個友元 
	friend class pal<C>;
}

2. 通用和特定的模板友好關系

template <typename T> 
class C {
	//pal的所有實例都是C的每個實例的友元 
	template <typename X> friend class pal;
}

class C {
	//pal的所有實例都是C的友元 
	template <typename X> friend class pal;
}
template <typename T> 
class C {
	//pal是C所有實例的友元 
	friend class pal;   //非模板類
}

註:可以將模板類型參數聲明為友元

六、模板參數

1. 使用類的類型成員

T::value_type * p;

上面這句代碼的默認含義是T類型的名為value_type的static數據成員與名為p的變量相乘。

為了顯式聲明value_type是一個模板類型參數的類型成員,我們可以如下定義:

typename T::value_type * p;

2. 默認模板實參

與函數默認實參一樣,對於一個模板參數,只有當它右側的所有參數都有默認實參時,它才可以有默認實參。

如果一個類模板為其所有模板參數都提供了默認實參,且我們希望使用這些默認實參,那就要:

template <class T = int> 
class C {
	//...
}; 
C<> c1;		//空<>表示我們希望使用默認實參 
C<double> c2;

七、成員模板

成員模板:本身是模板的成員函數,它不能是虛函數

1. 模板類的成員模板

template <typename T> 
class Blob {
	template <typename It> 		//此構造函數有自己的模板類型參數It 
	Blob(It b, It e);
	//...
}

template <typename T>
template <typename It>
Blob<T>::Blob(It b, It e) :data(make_shared<vector<T>>(b, e))
{
}

2. 非模板類的成員模板

與正常的函數模板沒有區別,只不過作用域是在類內

模板初步——定義模板