简体   繁体   English

嵌套类的同类朋友是否可以访问外部类成员?

[英]Does an in-class friend of a nested class have access to outer class members?

clang++, g++, and MSVC disagree on this code : clang ++,g ++和MSVC 对此代码不同意

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++ accepts the code as shown. clang ++接受如图所示的代码。 g++ and MSVC complain in f1 that A::E is inaccessible. g ++和MSVC在f1中抱怨A::E无法访问。 If function f2 is uncommented, all three compilers complain at its definition that A::E is inaccessible. 如果函数f2被取消注释,则所有三个编译器都在其定义中抱怨A::E是不可访问的。

Is f1 in fact valid? f1实际上有效吗?

The relevant Standard pieces I found are: 我找到的相关标准件是:

[class.access.nest] : [class.access.nest]

A nested class is a member and as such has the same access rights as any other member. 嵌套类是成员,因此具有与任何其他成员相同的访问权限。

Though this alone doesn't mean friends of the nested class have all the same rights as the nested class. 虽然这并不意味着嵌套类的朋友拥有与嵌套类完全相同的权限。

[class.access.base]/5 : [class.access.base] / 5

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 当在N类中命名时,可以在R点访问成员m

  • m as a member of N is public, or m作为N的成员是公共的,或

  • m as a member of N is private, and R occurs in a member or friend of class N , or m作为N的成员是私有的, R出现在N类的成员或朋友中,或者

  • m as a member of N is protected, and..., or m作为N的成员受到保护,并且......,或

  • there exists a base class B of N that is accessible at R , and m is accessible at R when named in class B . 存在可在R处访问的N的基类B ,并且当在类B命名时, m可在R处访问。

So f2 is invalid, because there the naming class for A::E is definitely A , there are no base classes involved, and the definition of f2 is not a member or friend of A and does not "occur in" a member or friend of A . 因此f2是无效的,因为A::E的命名类肯定是A ,没有涉及基类,并且f2的定义不是A的成员或朋友,并且不会“出现在”成员或朋友中A

In f1 the naming class for unqualified E is also A . f1中,不合格E的命名类也是A ([basic.lookup.unqual] says a lookup for the name E in class A::B is done first, but it's not "found" there, so then a lookup in class A is done, and the member is found.) But I guess the big question then is, does the definition of f1 "occur in" a member of A ? ([basic.lookup.unqual]表示首先在A::B类中查找名称E ,但在那里找不到它,因此在A类中进行查找,找到成员。)但我想那个大问题是, f1的定义是否“发生在” A的成员中? That member, if so, would have to be class A::B . 该成员如果是,则必须是class A::B

I think gcc and msvc are right. 我认为gcc和msvc是对的。

From [class.friend]/1 , emphasis mine: 来自[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 . 一类的一个朋友是给从类中使用private和protected成员名称权限的函数或类。 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. 这些声明给予朋友特殊的访问权限,但他们不会成为朋友级的指定朋友。

When you have friend E f1() , that gives f1 permission to use the private and protected names of B , specifically. 当你有friend E f1() ,它赋予f1使用B的私有和受保护名称权限。 E is not a private or protected name of B , it's a name that B simply has access too. E不是B的私有或受保护名称,它也是B只能访问的名称。


This is conceptually similar to [class.friend]/10 : 这在概念上类似于[class.friend] / 10

Friendship is neither inherited nor transitive. 友谊既不是遗传也不是传递。

Since it would imply that the rule is that f1 can access B 's stuff, and B can access A 's stuff, therefore f1 can access A 's stuff. 因为它意味着规则是f1可以访问B的东西,并且B可以访问A的东西,因此f1可以访问A的东西。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM