友元函数和静态数据成员
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(); }
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(); }
如何对好友函数体内使用的名称执行不合格名称查找?让我们考虑以下代码:
#include <iostream>
void foo();
class A
{
friend void foo(){ std::cout << a << std::endl; }
static int a;
};
int A::a = 10;
int main(){ foo(); }
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(); }