嵌套 class 的 in-class 好友是否可以访问外部 class 成员?
Does an in-class friend of a nested class have access to outer class members?
clang++、g++ 和 MSVC disagree on this code:
class A {
private:
enum class E { NO, YES };
class B {
private:
friend E f1() { return E::YES; }
// friend E f2();
};
};
// A::E f2() { return A::E::YES; }
int main() {}
clang++ 接受如图所示的代码。 g++ 和 MSVC 在 f1
中抱怨 A::E
不可访问。如果函数 f2
未注释,所有三个编译器都会抱怨其定义 A::E
不可访问。
f1
实际上有效吗?
我找到的相关标准件是:
A nested class is a member and as such has the same access rights as any other member.
尽管仅此一点并不意味着嵌套 class 的朋友拥有与嵌套 class.
相同的所有权利
The access to a member is affected by the class in which the member is named. This naming class is the class in which the member name was looked up and found. A member m
is accessible at the point R when named in class N
if
m
as a member of N
is public, or
m
as a member of N
is private, and R occurs in a member or friend of class N
, or
m
as a member of N
is protected, and..., or
there exists a base class B
of N
that is accessible at R, and m
is accessible at R when named in class B
.
所以f2
是无效的,因为A::E
的命名class肯定是A
,不涉及基数class,并且f2
的定义不是 A
的成员或朋友,也不会“出现在”A
的成员或朋友中。
在f1
中,不合格E
的命名class也是A
。 ([basic.lookup.unqual] 表示首先在 class A::B
中查找名称 E
,但在那里没有“找到”,因此然后在 class A
已完成,并且找到了成员。)但我想最大的问题是,f1
的定义是否“出现在”A
的成员中?如果是这样,该成员必须是 class A::B
.
我觉得gcc和msvc是对的
来自 [class.friend]/1,强调我的:
A friend of a class is a function or class that is given permission to use the private and protected member names from the class. A class specifies its friends, if any, by way of friend declarations. Such declarations give special access rights to the friends, but they do not make the nominated friends members of the befriending class.
当您拥有 friend E f1()
时,即授予 f1
使用 B
的私有名称和受保护名称 的权限,特别是。 E
不是 B
的私有或受保护名称,它是 B
也可以访问的名称。
这在概念上类似于 [class.friend]/10:
Friendship is neither inherited nor transitive.
因为这意味着规则是 f1
可以访问 B
的内容,而 B
可以访问 A
的内容,因此 f1
可以访问 A
的东西。
clang++、g++ 和 MSVC disagree on this code:
class A {
private:
enum class E { NO, YES };
class B {
private:
friend E f1() { return E::YES; }
// friend E f2();
};
};
// A::E f2() { return A::E::YES; }
int main() {}
clang++ 接受如图所示的代码。 g++ 和 MSVC 在 f1
中抱怨 A::E
不可访问。如果函数 f2
未注释,所有三个编译器都会抱怨其定义 A::E
不可访问。
f1
实际上有效吗?
我找到的相关标准件是:
A nested class is a member and as such has the same access rights as any other member.
尽管仅此一点并不意味着嵌套 class 的朋友拥有与嵌套 class.
相同的所有权利The access to a member is affected by the class in which the member is named. This naming class is the class in which the member name was looked up and found. A member
m
is accessible at the point R when named in classN
if
m
as a member ofN
is public, or
m
as a member ofN
is private, and R occurs in a member or friend of classN
, or
m
as a member ofN
is protected, and..., orthere exists a base class
B
ofN
that is accessible at R, andm
is accessible at R when named in classB
.
所以f2
是无效的,因为A::E
的命名class肯定是A
,不涉及基数class,并且f2
的定义不是 A
的成员或朋友,也不会“出现在”A
的成员或朋友中。
在f1
中,不合格E
的命名class也是A
。 ([basic.lookup.unqual] 表示首先在 class A::B
中查找名称 E
,但在那里没有“找到”,因此然后在 class A
已完成,并且找到了成员。)但我想最大的问题是,f1
的定义是否“出现在”A
的成员中?如果是这样,该成员必须是 class A::B
.
我觉得gcc和msvc是对的
来自 [class.friend]/1,强调我的:
A friend of a class is a function or class that is given permission to use the private and protected member names from the class. A class specifies its friends, if any, by way of friend declarations. Such declarations give special access rights to the friends, but they do not make the nominated friends members of the befriending class.
当您拥有 friend E f1()
时,即授予 f1
使用 B
的私有名称和受保护名称 的权限,特别是。 E
不是 B
的私有或受保护名称,它是 B
也可以访问的名称。
这在概念上类似于 [class.friend]/10:
Friendship is neither inherited nor transitive.
因为这意味着规则是 f1
可以访问 B
的内容,而 B
可以访问 A
的内容,因此 f1
可以访问 A
的东西。