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

     2023-02-25     176

关键词:

【中文标题】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,请在投票前阅读所有答案。

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

】类的方法中的本地类是这个类的朋友吗?【英文标题】:Isalocalclassinamethodofaclassafriendofthisclass?【发布时间】:2013-08-2814:52:15【问题描述】:我有一个外部类A。它有一个方法A::fun。在这个方法中,它有一个本地或内部类B。我的... 查看详情

alloca() 可以替代 C++ 中的自动指针吗?

】alloca()可以替代C++中的自动指针吗?【英文标题】:Canalloca()bereplacementforautopointersinC++?【发布时间】:2014-07-0312:56:29【问题描述】:alloca()用于从堆栈分配内存,堆栈在到达作用域末尾时自动释放。同时,C++中的自动指针确保... 查看详情

无法与 typedef 成为朋友:有啥特别的原因吗?

】无法与typedef成为朋友:有啥特别的原因吗?【英文标题】:Notabletobefriendtypedefs:anyparticularreason?无法与typedef成为朋友:有什么特别的原因吗?【发布时间】:2011-05-1315:03:51【问题描述】:structA;typedefAB;structCfriendstructB;;GCC4.7.0201... 查看详情

Visual Studio 2010 中的 C++ 访问修饰符自动缩进慢慢让我发疯 - 可以更改吗?

】VisualStudio2010中的C++访问修饰符自动缩进慢慢让我发疯-可以更改吗?【英文标题】:C++accessmodifierautoindentationinVisualStudio2010slowlydrivingmecrazy-canitbechanged?【发布时间】:2011-08-1803:04:29【问题描述】:在VisualStudio中编写C++时,它坚... 查看详情

“朋友”关系可以在 C++ 的类之间转移吗?

】“朋友”关系可以在C++的类之间转移吗?【英文标题】:Canthe"friend"relationshipbetransferredamongC++\'sclass?【发布时间】:2011-09-1814:30:24【问题描述】:假设A类是B类的朋友,B是C类的朋友,A是C的朋友还是C是A的朋友,或者两... 查看详情

删除 MovieClip 类会删除其中的 eventListeners 吗?

】删除MovieClip类会删除其中的eventListeners吗?【英文标题】:WillremovingaMovieClipclassremovetheeventListenersinsideit?【发布时间】:2014-07-2820:56:32【问题描述】:所以,我有一个类(称为A类),它添加了一个MovieClip类的子类(既是库中的... 查看详情

C++中的朋友和模板

】C++中的朋友和模板【英文标题】:friendandtemplateinC++【发布时间】:2018-07-1512:53:57【问题描述】:我的C++代码示例中有一个大问题。“朋友”和“模板”有问题。错误消息:Matrix.h:26:79:警告:朋友声明\'std::ostream&matrixClass::o... 查看详情

我可以直接继承实现以满足c ++中的接口吗

】我可以直接继承实现以满足c++中的接口吗【英文标题】:CanIdirectlyinheritimplementationstosatisfyinterfacesinc++【发布时间】:2017-04-2518:42:49【问题描述】:在C++中,如果我知道一个类会满足虚方法,是否可以修改下面的内容直接继承... 查看详情

C++ 编译器可以重新排序结构中的元素吗

】C++编译器可以重新排序结构中的元素吗【英文标题】:CanaC++compilerre-orderelementsinastruct【发布时间】:2010-10-2907:57:48【问题描述】:C++编译器(特别是g++)可以重新排序结构的内部元素吗?我看到一些奇怪的行为,我的结构包... 查看详情

在 Windows 窗体中使用 C++ 类会导致 System.AccessViolationException

】在Windows窗体中使用C++类会导致System.AccessViolationException【英文标题】:UsingAC++ClassInWindowsFormLeadstoSystem.AccessViolationException【发布时间】:2012-07-0516:58:33【问题描述】:我编写了一些使用各种C++库的C++类。我制作了一个Windows窗体... 查看详情

vector 可以成为 C++ 中队列的容器吗? [关闭]

】vector可以成为C++中队列的容器吗?[关闭]【英文标题】:Canvectorbeacontainerforqueueinc++?[closed]【发布时间】:2017-12-0920:50:40【问题描述】:vector不能作为队列的容器适配器是什么原因?我们非常感谢您的意见。【问题讨论】:后备... 查看详情

是啥使某物成为 C++ 中的抽象类 [重复]

】是啥使某物成为C++中的抽象类[重复]【英文标题】:WhatmakessomethinganAbstractClassinC++[duplicate]是什么使某物成为C++中的抽象类[重复]【发布时间】:2011-05-2520:36:31【问题描述】:可能重复:Whatisthedifferencebetweenaconcreteclassandanabstractcl... 查看详情

C++ 使用 std::find 在向量中查找类会引发错误

】C++使用std::find在向量中查找类会引发错误【英文标题】:C++findingclassinvectorusingstd::findraiseserrors【发布时间】:2020-09-2111:25:47【问题描述】:我正在尝试使用在std::vector中查找SnekNode对象autoit=std::find(snek_node_container.begin(),snek_node_... 查看详情

求c++中auto型的详细解释

auto是一个C/C++语言存储类型,仅在语句块内部使用,初始化可为任何表达式,其特点是当执行流程进入该语句块的时候初始化可为任何表达式。在函数内部定义的变量成为局部变量。在某些C语言教材中,局部变量称为自动变量... 查看详情

在类定义中使用内置数组,但大小推迟到派生类会导致隐藏吗?

...causehiding?【发布时间】:2016-04-2718:48:09【问题描述】:树中的每个类都依赖于与其他用于监控电压和电流传感器的类(通常命名为1、2、3...)有关系。问题是这些传感器中有多少取决 查看详情

有没有办法在 Java 中模拟 C++ 的“朋友”概念?

...能够在一个包中编写一个Java类,该类可以访问另一个包中的类的非公共方法,而不必使其成为另一个类的子类。这可能吗?【问题讨论】:【参考方案1】:这是我在JAVA中用来复制C++友元机制的一个小技巧。假设我 查看详情

用视图控制器类继承视图:新类会实例化基类的 UI 对象吗?

...roller类,其中包含一个视图和一些连接到MonoTouch应用程序中的插座的控件,它描述了一个自定义表 查看详情

C++ 中的双链表

】C++中的双链表【英文标题】:DoubleLinkedListsinC++【发布时间】:2010-12-2513:07:47【问题描述】:我有一个任务要求我们实现一个双向链表类。出于某种原因,他们将节点struct定义如下:structnodenode*next;node*prev;T*o;;在我看来,如果结... 查看详情