C++ 中的内部类会自动成为朋友吗?

Posted

技术标签:

【中文标题】C++ 中的内部类会自动成为朋友吗?【英文标题】:Are inner classes in C++ automatically friends? 【发布时间】:2011-06-28 04:12:45 【问题描述】:

如果我在 C++ 中定义了一个内部类,它会自动成为包含它的类的朋友吗?例如,这是否合法:

class Outer 
public:
    class Inner 
    public:
        void mutateOuter(Outer& o);
    ;

private:
    int value;
;

void Outer::Inner::mutateOuter(Outer& o) 
    o.value ++; // Legal?  Or not?

我之所以问,是因为在我尝试过的某些编译器 (VS2003) 上,此代码不起作用,但我至少听说过它确实适用于某些编译器。我在 C++ 规范中找不到关于此的相关部分,如果有人能引用一些具体的内容来说明它是否合法,那就太好了。

【问题讨论】:

嵌套类的成员函数遵循常规访问规则,对其封闭类的成员没有特殊的访问权限。:publib.boulder.ibm.com/infocenter/comphelp/v8v101/… @aaa- 感谢您的链接,但这似乎只适用于 IBM 的编译器,我知道它确实对规范有一些限制(例如,允许您获取标签的地址&& 运算符)。抱歉,如果我是这个问题的忠实拥护者,但我教的是一门 C++ 编程课程,并且想在告诉我的学生任何事情之前非常确定答案。 我不这么认为,因为如果是这种情况,那么我们就不需要在类主体中明确地声明友类。在这种情况下,一个声明就足够了 @template AFAIK 他们专门列出了非标准扩展。 顺便问一下,问题不是“它是不是朋友”,而是“它是否有私人访问权限”。 (前者足够,但不是必须的。) 【参考方案1】:

在我自己提出了或多或少相同的问题here 之后,我想分享(显然)C++11 的更新答案:

引用自https://***.com/a/14759027/1984137:

标准 $11.7.1

"嵌套类是一个成员,因此具有相同的访问权限 任何其他成员。封闭类的成员没有特殊的 访问嵌套类的成员;通常的访问规则应为 服从”

并且通常的访问规则指定:

"一个类的成员也可以访问该类的所有名称 有权限...”

标准中已给出具体示例:

class E 
    int x;
    class B  ;

    class I 
        B b; // OK: E::I can access E::B
        int y;
        void f(E* p, int i) 
            p->x = i; // OK: E::I can access E::x
        
    ;

【讨论】:

完全同意。我认为,应该修改这个问题的答案,因为问题中提供的代码现在可以正确编译。这是证明:link gcc 4.8.2 有一个仅在 gcc 4.9.0 中修复的错误。 gcc.gnu.org/bugzilla/show_bug.cgi?id=59482 简而言之:对于 C++11 及以后版本是,但对于 C++03 及以后版本则否。【参考方案2】:

直到 C++11(即 C++98 和 C++03)

在 C++98 和 C++03 中,嵌套类不能默认访问封闭类的 privateprotected 成员。

C++ 标准 (2003) 在 $11.8/1 [class.access.nest] 中说,

嵌套类的成员没有 对成员的特殊访问 封闭类,也不是类或 赋予友谊的功能 到封闭类;通常 访问规则(第 11 条)应 服从了。 封闭的成员 类没有特殊的访问权限 嵌套类的成员; 通常 访问规则(第 11 条)应 服从。

标准本身的示例:

class E 

    int x;
    class B  ;
    class I 
    
        B b; // error: E::B is private
        int y;
        void f(E* p, int i)
        
           p->x = i; // error: E::x is private
        
   ;
   int g(I* p)
   
       return p->y; // error: I::y is private
   
;

C++11 起

自 C++11 起,上述限制已被删除。现在嵌套类可以访问封闭类的privateprotected 成员:

class E 

    int x;
    class B  ;
    class I 
    
        B b; // ok: even though E::B is private
        int y;
        void f(E* p, int i)
        
           p->x = i; // ok: even though E::x is private
        
   ;
   int g(I* p)
   
       return p->y; // ok: even though I::y is private
   
;

希望对您有所帮助。

【讨论】:

@templatetypedef:我知道嵌套类不能访问封闭类的私有成员,但引用了错误的引用。无论如何,我更正了参考! 在省略g() 之后,代码compiles fine 使用C++11 以后。应该更新答案。 如果您使用有关 C++11 的相关信息更新答案,那就太好了,因为有一个关键区别;) @Alexey:已更新。 我尝试在 xcode 9.2 上使用其默认编译器 (LLVM 9.0) 编译此代码,但它没有编译。它在 return p->y 行失败。看来访问父类私有成员是可以的,但是从父类访问子类私有成员就不行了。【参考方案3】:

由于提问者似乎已经接受了其中一个答案,这只是 补充。 该标准似乎改变了关于可访问性的规范。

C++98 中的§11.8/1 状态:

嵌套类的成员没有 对成员的特殊访问 封闭类,也不是类或 赋予友谊的功能 到封闭类;通常 应遵守访问规则。

N1804(TR1 之后)中的§11.8/1 规定:

嵌套类是成员,因此 具有与任何相同的访问权限 其他成员。

我认为当前的 C++ 编译器遵循更新的规范。

【讨论】:

嵌套类是一个成员,但是嵌套类成员可以被认为是封闭类的成员吗?这并不明显。嵌套类本身(不是它的成员)可以像这样访问封闭类的成员:class Enclosing private: enum PrivateEnum VALUE; class Nested /*accessing enclosing class' member type*/ PrivateEnum e;; ;. @SergeyTachenov:嗨。 N1804 中的 §11.8/1 还指出:封闭类的成员对嵌套类的成员没有特殊的访问权限应遵守通常的访问规则。 该语句与 C++98 没有任何变化。所以,对于从封闭类到嵌套类的访问(与templatetypedef的问题相反),通常的访问规则适用。 @Ise,我不是在谈论访问嵌套类的成员,这是一个完全不同的问题。我只是不确定“嵌套类是成员”的概念是否也适用于嵌套类的成员。那么多层嵌套呢? @SergeyTachenov:对不起,我误解了你的评论。如果您的意思是标准中是否允许class A int i; class B struct C void f( A* x ) x->i = 0; ; ; ;,我想允许它是标准的意图。 VC8、g++3.4.5 和 Comeau online 都允许。但我不能说确切的事情。如果您担心,我建议您在 *** 中发布该问题。比我有更详细知识的人会回答。 @Ise,很抱歉把不相关的东西放进去。最初我是在评论 N1804 的引用:“嵌套类是成员” - 这是否意味着嵌套类的成员是封闭类也?我的意思是,在class A int i; class B A *a; int f() return a->i; ; ; 中,B 类是 A 类的成员,但 B::f() 是 A::B 类的成员,而不是 A!但是我刚刚从 DR 45 中找到了另一个引用,这可能会澄清这一点:“一个类的成员也可以访问它所属的类的所有名称。”换句话说,B::f() “继承”了 B 类的访问权限。【参考方案4】:

此答案与(过时的)C++03 规范有关。在此问题上接受的答案是最新的。

好吧,我现在问这个问题感觉很傻,因为我刚刚找到了规范中涵盖此问题的相关部分:§11.8/1:

嵌套类的成员对封闭类的成员没有特殊的访问权,也对与封闭类授予友谊的类或函数没有特殊的访问权限;应遵守通常的访问规则(第 11 条)。 封闭类的成员对嵌套类的成员没有特殊的访问权限;应遵守通常的访问规则(第 11 条)

(我的重点)

所以看起来没有,内部类没有特殊的访问权限。

【讨论】:

你误解了那一段。没有11.8.1,你的意思是11.8p1(或“11.8/1”)吗? @Fred Nurk- 哎呀,意思是 11.8/1。会修复的。 @Fred Nurk- 另外,当您说我误解了它时,是指我对它的解释不正确,还是只是贴错了标签? 和@Fred:templatetypedef 是正确的。请看我的帖子。我还引用了标准本身的例子。【参考方案5】:

我不知道确切的位置,但我确实记得阅读规范并发现一个类中的任何私有数据对所有其他类都隐藏,包括嵌套类。

基本上,嵌套类定义了一定的范围,而不是访问权限。

【讨论】:

你错了,但我只是 -1'ing 因为不知何故,即使附近引用了正确的答案,这也得到了 +1'd。 @Voters,请在投票前阅读所有答案。

以上是关于C++ 中的内部类会自动成为朋友吗?的主要内容,如果未能解决你的问题,请参考以下文章

Java泛型知识总结篇

内部类

类的方法中的本地类是这个类的朋友吗?

[ C++ ] 类与对象(下) 初始化列表,友元,static成员,内部类

Java语法糖

Java中的匿名内部类及内部类的二三事