今天我写了一个处理内存的类,我需要在其中使用另一个嵌套类。主类有一个方法可以返回这个嵌套类的对象:
class Main
{
private:
class Inner
{
};
public:
Inner foo()
{ return {}; }
};
然后我这样做了:
Main m;
auto a = m.foo();
它奏效了。但是你不能直接创建这样的对象,因为嵌套类是私有的:
Main::Inner a; //ошибка
老实说,我有点困惑,我感兴趣的是这是一个缺陷还是它是故意的(直到现在我还没有在任何地方看到这个)。
因为 public/private 只控制名称,并且只在编译时。在这种情况下,auto 不属于这个规则,因为编译器粗略地说,会生成一个 typedef。typedef 可以“改变函数的可访问性”。
这是为什么?显然是因为 auto 在大多数情况下会从模板中复制行为 things,并且(在模板魔术中)有很多情况下类型隐藏在一侧而在另一侧可见。
例如,这是一个示例(位于下面的链接中):
f.Baz() 的类型可能一点也不好玩,但它确实有效。
再次。private/public 影响名称,但不影响类型本身,尽管在大多数人的心目中它们是同一回事。而汽车,可以说是又给了一个名字。
关于enSO的同样问题
是的,这确实是C++的访问控制机制的缺陷之一。但是,
auto
这里的使用没有任何作用。该行auto a = m.foo();
只调用public
该函数,没有任何访问限制。有问题的地方实际上是在声明具有公共访问权限的东西时使用具有私有访问权限的标识符。在public: Inner foo()
访问控制行上,这允许,尽管实际上类的私有填充被丢弃并且先前设置的访问修饰符Inner
变得无用。在 c# 或 kotlin 等更智能的语言中,访问控制的实现更加负责,并且在声明具有更严格访问权限的内容时尝试使用更严格的标识符会导致构建错误。在 C++ 中,有人提议引入类似的改进,但这会破坏向后兼容性(就像大多数好的提议一样)。现在,您可以使用 Misra C++ 的建议:严格按照
public
、protected
、 . 的顺序在类中放置声明private
。使用这种方法,在访问受限的部分中不能使用更多受限的名称,因为它们将在稍后声明:在线编译器