天天看點

C++模闆類内友元(友元類,友元函數)聲明的三種情況

根據《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();
    //...
};
           

繼續閱讀