友元函数和静态数据成员

Friend functions and static data members

如何对好友函数体内使用的名称执行不合格名称查找?让我们考虑以下代码:

#include <iostream>

void foo();

class A
{
    friend void foo(){ std::cout << a << std::endl; }
    static int a;
};

int A::a = 10;

int main(){ foo(); }

DEMO

N4296::7.3.1.2/3 [namespace.memdef] 中的标准规定:

If a friend declaration in a non-local class first declares a class, function, class template or function template the friend is a member of the innermost enclosing namespace.

所以,我预计未找到不合格的名称查找 A::a,但确实找到了。我故意把 A::a 声明放在朋友的函数定义之后,希望它不会被发现。朋友不合格姓名查找的实际规则是什么?

答案很简单:

N4296::3.4.1/8 [basic.lookup.unqual] :

For the members of a class X, a name used in a member function body, in a default argument, in an exceptionspecification, in the brace-or-equal-initializer of a non-static data member (9.2), or in the definition of a class member outside of the definition of X, following the member’s declarator-id31, shall be declared in one of the following ways:

[...]

(8.2) — shall be a member of class X or be a member of a base class of X (10.2),

[...]

N4296::3.4.1/9 [basic.lookup.unqual] :

Name lookup for a name used in the definition of a friend function (11.3) defined inline in the class granting friendship shall proceed as described for lookup in member function definitions.

就是这样。

更新:

内联在这里很重要。这就是为什么定义在 class 定义之外的友元函数不能直接使用 class 的静态成员。例如,下面的代码会报编译时错误:

#include <iostream>

class A
{
    static int a;
    friend void foo();
};

int A::a = 10;

void foo(){ std::cout << a << std::endl; }



int main(){ foo(); }

DEMO