inheritance:“A”是一个不可访问的“B”

$ cat inheritance.cpp #include <iostream> using namespace std; class A { }; class B : private A { }; int main() { A* ab = new B; } $ $ g++ inheritance.cpp inheritance.cpp: In function 'int main()': inheritance.cpp:9: error: 'A' is an inaccessible base of 'B' $ 

我只是不明白这个错误。

据我所知,正如本教程所证实的那样, privateinheritance只应该改变class B的成员对于外部世界的可见性。

我认为私人指定者不仅仅是在这里改变class B成员的知名度。

  • 我得到这个错误是什么,这是什么意思?
  • 基本上在C ++中允许这种types的代码有什么问题? 看起来完全无害。

通过将inheritance隐藏起来,基本上就是说,即使B从Ainheritance的事实是私有的,外部世界也是不可访问/可见的。

没有深入讨论如果允许的话会发生什么,简单的事实是这是不允许的。 如果你想使用一个指向base的指针来引用一个派生types的对象,那么你几乎坚持使用公有inheritance。

编辑:由于有人去发送电子邮件的问题,要求更多的信息,如果这是允许的话会发生什么,我想我会详细阐述一下。

基本的问题是私人inheritance不一定打算遵循Liskov替代原则 。 公共inheritance声明派生的对象可以替代基类的对象,并且仍然会产生适当的语义。 然而,私有inheritance并没有主张。 私人inheritance隐含的关系的通常描述是“以…实现”。

公有inheritance意味着派生类保持基类的所有function,并且可能增加更多的function。 私有inheritance通常意味着或多或less的相反情况:派生类使用通用基类来实现具有更多受限接口的东西。

举个例子,假设C ++标准库中的容器是使用inheritance而不是模板实现的。 在当前系统中, std::dequestd::vector是容器,而std::stack是一个容器适配器,它提供了一个更受限制的接口。 由于它基于模板,因此可以使用std::stack作为std::dequestd::vector的适配器。

如果我们想提供与inheritance基本相同的东西,我们可能会使用私有inheritance,所以std::stack就像这样:

 class stack : private vector { // ... }; 

在这种情况下,我们绝对希望用户能够操纵我们的stack ,就好像它是一个vector 。 这样做可能(也可能会)违反堆栈的期望(例如,用户可以在中间插入/移除项目,而不是按照预期的纯粹堆栈式的方式)。 我们基本上使用vector来实现我们的堆栈,但是如果(例如)我们改变了stack stand的实现(不依赖于基类),或者用std::deque来重新实现,我们希望这影响任何客户端代码 – 客户端代码,这应该只是一个堆栈,而不是一些专门的vector(或deque)品种。

私人inheritance只能改变B级的成员对外界的看法

它确实。 而如果

 A* p = new B; 

被允许,那么任何B的inheritance成员都可以从外部访问,只需要创build一个A* 。 由于它们是私人inheritance的,因此访问是非法的,上传也是非法的。

clang++给出了一个更容易理解的错误信息:

 example.cpp:9:13: error: cannot cast 'B' to its private base class 'A' A* ab = new B; ^ example.cpp:6:11: note: declared private here class B : private A { }; ^~~~~~~~~ 1 error generated. 

我不是一个C ++专家,但它看起来就是不被允许的。 我会徘徊在规范周围,看看我想出了什么。

编辑:这里是规范的相关参考 – 第4.10指针转换 ,第3段:

types“指向cv D指针”(其中D是类types)的值可以转换为types“指向cv B指针”的值,其中B是D的基类。 如果BD的不可访问或模糊的基类,则需要这种转换的程序是不合格的。

这很简单: A是私人inheritance的事实意味着B扩展A的事实是一个秘密,只有B “知道”它。 这是私人inheritance的定义。

私有inheritance意味着派生类之外的inheritance信息是隐藏的。 这意味着您不能将派生类转换为基类:调用者不知道关系。