模板類和友元函數

模板類的友元分3類:
非模板友元
約束(bound)模板友元,即友元的類型取決於類被實例化時的類型。
非約束(undound)模板友元,即友元的所有具體化都是類的每一個具體化的友元。

1.模板類的非模板友元函數

template<class T>
class HasFriend
{ friend void counts();  //friend to all HaFriend instantiations
  ... };

上訴聲明使counts()函數成爲模板所有實例化的友元。


     counts()函數不是通過對象調用的,也沒有對象參數。它可以訪問全局對象;可以使用全局指針訪問非全局對象;可以創建自己的對象;可以訪問獨立於對象的模板類的靜態數據成員。

 

爲友元函數提供模板類參數,必須提供特定的具體化,如HasFriend<short>。

要提供模板類參數,必須指明具體化:
template<class T>
class HasFriend
{ friend void report(HasFriend<T> & ); 
 // bound template friend
  ... };

 

     也就是說,帶HasFriend<int>參數的report()將成爲HasFriend<int>類的友元函數。同樣,帶HasFriend<double>參數的report()將是report()的一個重載版本——它將是HasFriend<double>類的友元。

 

report()本省並不是模板函數,而只是使用一個模板作參數。這意味着必須爲要使用的友元定義顯示具體化:
void report(HasFriend<short> & ) {...} //explicit specialization for short
void report(HasFriend<int> & ) {...}     //explicit specialization for int

 

2.模板類的約束模板友元函數
修改前一個上面的範例,使友元函數本身成爲模板。使類的每一個具體化都獲得與友元匹配的具體化。包含以下三步:

首先,在類定義的前面聲明每個模板函數:
template <typename T> void counts();
template <typename T> void report(T &);

 

然後在函數中再次將模板聲明爲友元。這些語句根據類模板參數的類型聲明具體化:
template<class TT>
class HasFriend
{ friend void counts<TT>();
  friend void report<>(HasFriend<TT> &);
  ... };

 

    上述聲明中的<>指出這是模板具體化。對於report(),<>可以爲空,這是因爲可以從函數參數推斷出模板類型參數(HasFriend<TT>)。不過,也可以使用report<HasFriend<TT> >(HasFriend<TT> &)。但counts()函數沒有參數,因此必須使用模板參數句法(<TT>)來指明其具體化。還需要注意的是,TT是HasFriend類的參數類型。

 

假設聲明瞭這樣一個對象:
HasFriend<int> squack;

則編譯器將用int替換TT,並生成下面的類定義:
class HasFriend<int>
{ friend void counts<int>();
  friend void report<>(HasFriend<int> &);
  ... };

於是,模板具體化counts<int>()和report<HasFriend<int> >()被聲明爲HasFriend<int>類的友元。

 

最後,程序必須爲友元提供模板定義,例如:
template <typename T>
void counts() { cout << HasFriend<T>::x << endl;}

template <typename T>
void report(T & hf) {cout << hf.x << endl;}

 

調用時,counts()需要提供具體化參數類型。report()只需直接調用,例如:
counts<int>();  //調用HasFriend<int>的友元函數
HasFriend<double> hfdb;
report(hfdb);   //調用HasFriend<double>的友元函數

3.模板類的非約束模板友元函數
    通過在類內部聲明友元函數模板,可以創建非約束友元函數,即每個函數具體化都是每個類具體化的友元:
template <typename T>
class ManyFriend
{...
 template <typename C,typename D> friend void show(C &,D &);
};

 

在類外定義該友元:
template <typename C,typename D>
void show(C & c,D & d){ ... }

 

假如創建ManyFriend<int>類對象(hfi1)和ManyFriend<double>類對象(hfi2),傳遞給show(),那麼編譯器將生成如下具體化定義:
void show<ManyFriend<int> &,ManyFriend<double> &>
         (ManyFriend<int> & c,ManyFriend<double> & d){ ... }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章