根據《C++ Primer》第三版16.4節的叙述,C++類模闆友元分為以下幾種情況
1.非模闆友元類或友元函數。 書上給了一個例子:
class Foo
{
void bar();
};
template <class T>
class QueueItem
{
friend class foobar;
friend void foo();
friend void Foo::bar();
//....
};
注意,如果要把普通函數和類聲明為友元,前面不需要聲明或定義。但是,如果要把類成員函數聲明為友元,則前面必須有類的定義(注意不是聲明,是定義),因為一個類成員隻能由該類的定義引入。
2.綁定的友元類模闆或函數模闆。 例子如下:
template <class Type>
class foobar{ ...};
template <class Type>
void foo(QueueItem<Type>);
template <class Type>
class Queue
{
void bar();
//...
};
template <class Type>
class QueueItem
{
friend class foobar<Type>;
friend void foo<Type>(QueueItem<Type>);
friend void Queue<Type>::bar();
//...
};
需要注意以下兩點:
a.與非模闆函數或類不同,模闆函數或類聲明為友元之前必須在前面聲明過 ,否則無法通過編譯。
b.類或模闆函數聲明為友元時,在其名稱後要加上Type,否則會編譯報錯。比如對于普通函數foo,如果沒有加的話編譯器會将其作為非模闆函數對待,也就是說,對于QueueItem,編譯器會查找void foo(QueueItem),而對template <class Type> void foo(QueueItem<Type>)視而不見,如果沒找到非模闆函數,編譯器就會報錯。
3.非綁定友元類模闆或函數模闆。 舉例如下:
template <class Type>
class QueueItem
{
template <class T>
friend class foobar;
template <class T>
friend void foo(QueueItem<T>);
template <class T>
friend void Queue<T>::bar();
//...
};