在命名空间内的类的友元函数

时间:2012-06-07 17:49:19

标签: c++ namespaces friend

关于这个代码,我有两个问题:

namespace A { class window; }

void f(A::window);

namespace A
{
    class window
    {
    private:
       int a;
       friend void ::f(window);
    };
}

void f(A::window rhs)
{
    std::cout << rhs.a << std::endl;
}

1)为什么我需要通过执行:: f(window)来限定窗口类中的成员函数f是全局的?

2)为什么我需要在这种特殊情况下预先声明函数f(A :: window),而当在类名称空间内没有定义类时,可以在函数声明为朋友之后声明函数

3 个答案:

答案 0 :(得分:4)

当您将f()声明为朋友时,如果尚未出现转发声明,则它实际上已在包含类的封闭命名空间中完成(在本例中为A)。

所以这......

namespace A
{
    class window
    {
    private:
        friend void ::f(window);
    };
}

基本上就是这个......

namespace A
{
    class window;
    void f(window);

    class window
    {
    private:
        friend void f(window);
    };
}

编辑:以下是C ++标准的一个片段,明确说明了这种情况:

  

标准7.3.1.2 / 3:

     

首先在名称空间中声明的每个名称都是该名称空间的成员。 如果非本地类中的朋友声明首先声明一个类或函数,那么友元类或函数是最内层封闭命名空间的成员。非限定查找找不到朋友的名称(3.4.1 )或通过限定查找(3.4.3),直到在该命名空间范围内提供匹配声明(在授予友谊的类定义之前或之后)。

答案 1 :(得分:3)

对于1),您的函数不在命名空间中,因此您必须使用::来告诉编译器在命名空间之外搜索它。

否则,它只会查找命名空间内的函数(这就是它们存在的原因)。 Koenig查找在这里不适用,因为窗口类在命名空间内。

不太确定2)但是我敢打赌它与1)有关。

答案 2 :(得分:1)

1)因为函数f是在当前命名空间之外声明和定义的。如果您将类的定义移动到与函数相同的名称空间中,无论是全局函数还是其他函数,您都不需要。

2)你总是需要在引用之前声明一个函数。您的类使用friend语句引用该函数。