[英]Inheritance: 'A' is an inaccessible base of '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'
$
我只是不明白这个错误。
据我了解,正如本教程所确认的那样, private
继承应该只改变class B
成员对外界可见的方式。
我认为私有说明符所做的不仅仅是改变class B
成员的可见性。
通过将继承设为私有,您基本上是在说,即使 B 从 A 继承(根本)这一事实也是私有的——外部世界无法访问/可见。
无需对如果允许会发生什么进行冗长的讨论,简单的事实是它是不允许的。 如果您想使用指向基类的指针来引用派生类型的对象,那么您几乎无法使用公共继承。
私有继承不一定是(甚至通常)打算遵循Liskov替换原则。 公有继承断言派生对象可以取代基类的一个对象,和正确的语义仍然将导致。 私有继承并没有断言这一点。 私有继承所隐含的关系的通常描述是“是根据……实现的”。
公共继承意味着派生类维护基类的所有功能,并可能添加更多功能。 私有继承通常意味着或多或少相反:派生类使用通用基类来实现具有更受限接口的东西。
仅举个例子,让我们暂时假设 C++ 标准库中的容器是使用继承而不是模板实现的。 在目前的系统中, std::deque
和std::vector
是容器, std::stack
是容器适配器,提供了更受限的接口。 由于它基于模板,因此您可以使用std::stack
作为std::deque
或std::vector
的适配器。
如果我们想提供本质上相同的继承,我们可能会使用私有继承,所以std::stack
将类似于:
class stack : private vector {
// ...
};
在这种情况下,我们绝对不希望用户能够像操作vector
一样操作我们的stack
。 这样做可能(并且可能会)违反堆栈的期望(例如,用户可以在中间插入/删除项目,而不是像预期的那样纯粹的类似堆栈的方式)。 我们基本上使用vector
作为实现堆栈的便捷方式,但是如果(例如)我们更改了stack
独立的实现(不依赖于基类)或根据std::deque
重新实现它,我们不希望这影响任何客户端代码——对于客户端代码,这应该只是一个堆栈,而不是一些特殊的向量(或双端队列)。
私有继承应该只改变 B 类成员对外界可见的方式
确实如此。 而如果
A* p = new B;
被允许,那么任何B
的继承成员都可以从外部世界访问,只需创建一个A*
。 由于它们是私下继承的,因此访问是非法的,上行也是如此。
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 段:
“指向cv
D
指针”类型的纯右值(其中D
是类类型)可以转换为“指向 cvB
指针”类型的纯右值,其中 B 是D
的基类。 如果B
是D
的不可访问或不明确的基类,则需要这种转换的程序是格式错误的。
这很简单: A
被私下继承的事实意味着B
扩展A
的事实是一个秘密,只有B
“知道”它。 这就是私有继承的定义。
私有继承意味着在派生类之外,继承信息是隐藏的。 这意味着您不能将派生类强制转换为基类:调用者不知道这种关系。
这是工作
#include <iostream>
using namespace std;
class A{
public:
virtual void update() = 0;
};
class B: public A{
public:
virtual void update(){std::cout<<"hello";};
};
int main()
{
A *a = new B();
a->update();
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.