發表一點自己對 《C++ Primer 5th》模板那塊的理解, 歡迎指正
一對一友好關係
在類模板與另一個模板(模板類或模板函數)間建立對應實例及其友好關係,爲了在類模板中引用另一個類模板或函數的一個特定實例,必須先聲明另一個模板:
方便理解和敘述,將含友元的類稱爲主類,將要做友元類的模板類稱爲客類
//爲了在類裏面引用 BlobPtr<T> 和 poerator==<T> 現在類之前聲明
template <typename> class BlobPtr;
template <typename> class Blob;
template <typename T>
bool operator==(const Blob<T>&, const Blob<T>&);
template <typename T>
class Blob{
friend class BlobPtr<T>; //客類
friend bool operator==<T>; //主類
(const Blob<T>&, const Blob<T>&);
....
};
//模板類友元運算符重載函數定義:
template <typename T>
bool operator==<T>(const Blob<T>& lhs, const Blob<T>& rhs)
{
...
}
也就是說只有 BlobPtr<int> operator==<int>
纔是 Blob<int>
的友元.而 BlobPtr<std::string>
不是 Blob<int>
的友元
通用和特定的模板友好關係
- 將客類的每個實例都聲明爲主類的友元
- 將客類的特定實例聲明爲主類的友元
對於第一種情況不需要在模板類前置聲明
template <typename T>
class C1
{
//C1每個實例將擁有相同實例化的Pal聲明爲友元
friend class Pal<T>;
//Pal2所有實例都是 C1 的每個實例的友元 不需前置聲明
template <typename X> friend class Pal2;
};
Pal2<int>, Pal2<std::string>
都是 C1<int>
或者 C1<std::string>
的友元
第二種情況需要前置聲明
template <typename T> class Pal;
class C2 //C2不是模板類
{
//C2每個實例將 用C1類型實例化的Pal 聲明爲友元
friend class Pal<C1>;
};
總結:
- 如果想將客類的所有實例作爲主類每個實例的友元,那麼不需要再主類前聲明客類模板,也不需要聲明友元時加,並且在主類內部聲明客類爲主類友元之前要加上客類的模板參數列表,而且還不能和主類參數名一樣,如:
template<typename T> class 主類
{
template <typename X> //模板參數和主類不一樣
friend 客類;
};
- 如果只想將擁有和主類相同實例的客類或模板函數作爲主類的友元,那就先在主類前聲明客類(帶模板參數列表template), 然後在主類中聲明客類
friend
(帶模板參數,不帶template)並且模板參數<T>
需要和主類的參數名相同。
template<typename > class 客類;
template<typename T> class 主類
{
friend 客類<T>; //模板參數和主類一致
};