命名空间内类的友元函数

friend functions of a class inside a namespace

本文关键字:友元 函数 命名空间      更新时间:2023-10-16

我对下面的代码有两个问题:

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(窗口) 来限定窗口类内的成员函数 f 是全局的?

2)为什么我需要在这种特殊情况下预先声明函数f(A::window),而当类未在命名空间中定义时,可以在函数声明为友元后声明函数。

当您将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),你的函数不在命名空间中,所以你必须使用 :: 告诉编译器在命名空间之外搜索它。

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

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

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

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