C++ 继承:“A”是“B”的不可访问的基础
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9661936/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Inheritance: 'A' is an inaccessible base of 'B'
提问by Lazer
$ 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'
$
I just do not understand this error.
我只是不明白这个错误。
As I understand, and as this tutorialconfirms, private
inheritance should only change how the members of class B
are visible to the outside world.
据我了解,正如本教程所确认的那样,private
继承应该只改变 的成员对class B
外界可见的方式。
I think the private specifier is doing more than just change visibility of class B
members here.
我认为私有说明符所做的不仅仅是改变class B
这里成员的可见性。
- What do I get this error and what does it mean?
- Basically what is wrong with allowing this type of code in C++? Looks totally harmless.
- 我得到这个错误是什么意思?
- 基本上在 C++ 中允许这种类型的代码有什么问题?看起来完全无害。
回答by Jerry Coffin
By making the inheritance private, you're basically saying that even the fact that B inherits from A (at all) is private -- not accessible/visible to the outside world.
通过将继承设为私有,您基本上是在说,即使 B 从 A 继承(根本)这一事实也是私有的——外部世界无法访问/可见。
Without getting into a long-winded discussion of what would happen if it was allowed, the simple fact is that it's not allowed. If you want to use a pointer to base to refer to an object of derived type, then you're pretty much stuck with using public inheritance.
无需对如果允许会发生什么进行冗长的讨论,简单的事实是它是不允许的。如果您想使用指向基类的指针来引用派生类型的对象,那么您几乎无法使用公共继承。
Private inheritance is notnecessarily (or even normally) intended to follow the Liskov substitution principle. Public inheritance asserts that a derived object can be substituted for an object of the base class, and proper semantics willstill result. Private inheritance does notassert that though. The usual description of the relationship implied by private inheritance is "is implemented in terms of".
私有继承并不一定(甚至常)打算遵循Liskov替换原则。公有继承断言派生对象可以取代基类的一个对象,和正确的语义将仍然导致。私有继承并没有断言这一点。私有继承所隐含的关系的通常描述是“是根据……实现的”。
Public inheritance means a derived class maintains all the capabilities of the base class and potentially adds more besides. Private inheritance often means more or less the opposite: that the derived class uses a general base class to implement something with a more restricted interface.
公共继承意味着派生类维护基类的所有功能,并可能添加更多功能。私有继承通常意味着或多或少相反:派生类使用通用基类来实现具有更受限接口的东西。
Just for example, let's assume for the moment that the containers in the C++ standard library were implemented using inheritance rather than templates. In the current system, std::deque
and std::vector
are containers, and std::stack
is a container adapter that provides a more restricted interface. Since it is based on templates, you can use std::stack
as an adapter for either std::deque
or std::vector
.
仅举个例子,让我们暂时假设 C++ 标准库中的容器是使用继承而不是模板实现的。在目前的系统中,std::deque
和std::vector
是容器,std::stack
是提供更受限接口的容器适配器。由于它基于模板,因此您可以将其std::stack
用作std::deque
或的适配器std::vector
。
If we wanted to provide essentially the same with inheritance, we would probably use private inheritance, so std::stack
would be something like:
如果我们想提供本质上相同的继承,我们可能会使用私有继承,所以std::stack
会是这样的:
class stack : private vector {
// ...
};
In this case, we definitely do notwant the user to be able to manipulate our stack
as if it were a vector
. Doing so could (and likely would) violate the expectations of a stack (e.g., the user could insert/remove items in the middle, rather than a purely stack-like fashion as intended). We're basically using vector
as a convenient way to implement our stack, but if (for example) we changed the implementation for stack
stand alone (with no dependence on a base class) or re-implement it in terms of std::deque
, we do notwant that to affect any client code -- to the client code, this is supposed to be just a stack, not some specialized variety of vector (or deque).
在这种情况下,我们绝对不希望用户能够stack
像操作vector
. 这样做可能(并且可能会)违反堆栈的期望(例如,用户可以在中间插入/删除项目,而不是像预期的那样纯粹的类似堆栈的方式)。我们基本上vector
是作为一种方便的方式来实现我们的堆栈,但是如果(例如)我们改变了stack
独立的实现(不依赖于基类)或重新实现它std::deque
,我们不希望那样影响任何客户端代码——对于客户端代码,这应该只是一个堆栈,而不是一些特殊的向量(或双端队列)。
回答by Ben Voigt
private inheritance should only change how the members of class B are visible to the outside world
私有继承应该只改变 B 类成员对外界可见的方式
It does. And if
确实如此。而如果
A* p = new B;
were allowed, then the inherited members of any B
could be accessed from the outside world, just by making a A*
. Since they're privately inherited, that access is illegal, and so is the upcast.
被允许,则B
可以从外部世界访问any 的继承成员,只需创建一个A*
. 由于它们是私下继承的,因此访问是非法的,上行也是如此。
回答by Carl Norum
clang++
gives a slightly more understandable error message:
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.
I'm not a C++ expert, but it looks like it's just simply not allowed. I'll go poke around the spec and see what I come up with.
我不是 C++ 专家,但看起来这只是不允许的。我会去看看规范,看看我想出了什么。
Edit: here's the relevant reference from the spec - Section 4.10 Pointer conversions, paragraph 3:
编辑:这是规范中的相关参考 - 第4.10节指针转换,第 3 段:
A prvalue of type "pointer to cv
D
", whereD
is a class type, can be converted to a prvalue of type "pointer to cvB
", where B is a base class ofD
. IfB
is an inaccessible or ambiguous base class ofD
, a program that necessitates this conversion is ill-formed.
类型为“指向cv 的指针”的纯右值
D
,其中D
是类类型,可以转换为类型为“指向 cv 的指针”的纯右值B
,其中 B 是 的基类D
。如果B
是 的不可访问或模棱两可的基类D
,则需要进行此转换的程序是格式错误的。
回答by Ernest Friedman-Hill
It's pretty simple: the fact that A
is inherited privately means that the fact that B
extends A
is a secret, and only B
"knows" it. That is the very definition of private inheritance.
这很简单:A
私下继承的事实意味着B
扩展的事实A
是一个秘密,只有B
“知道”它。这就是私有继承的定义。
回答by tmpearce
Private inheritance means that outside the derived class, the inheritance information is hidden. That means you can't cast the derived class to the base class: the relationship isn't known to the caller.
私有继承意味着在派生类之外,继承信息是隐藏的。这意味着您不能将派生类强制转换为基类:调用者不知道这种关系。
回答by Deniz Babat
This is working
这是工作
#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;
}