继承:"A"是"B"不可访问的基础
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
成员在这里的可见性。
- 为什么我在继承时收到此错误,这意味着什么?
- 基本上,在C++中允许这种类型的代码有什么问题?看起来完全无害。
通过将继承设为私有,你基本上是在说,即使是 B 从 A 继承的事实(完全(也是私有的——外部世界无法访问/可见。
在不进行冗长的讨论的情况下会发生什么,简单的事实是它不允许。如果要使用指向 base 的指针来引用派生类型的对象,那么您几乎只能使用公共继承。
私人继承不一定(甚至通常(遵循利斯科夫替代原则。公共继承断言派生对象可以替换为基类的对象,并且仍然会产生正确的语义。不过,私有继承并没有断言这一点。对私人继承所隐含的关系的通常描述是"根据"实施。
公共继承意味着派生类维护基类的所有功能,并可能添加更多功能。私有继承通常意味着或多或少相反:派生类使用通用基类来实现具有更受限制的接口的内容。
举个例子,让我们暂时假设C++标准库中的容器是使用继承而不是模板实现的。在当前系统中,std::deque
和std::vector
是容器,std::stack
是提供更受限制的接口的容器适配器。由于它基于模板,因此您可以将std::stack
用作std::deque
或std::vector
的适配器。
如果我们想提供基本相同的继承,我们可能会使用私有继承,所以std::stack
是这样的:
class stack : private vector {
// ...
};
在这种情况下,我们绝对不希望用户能够 操纵我们的stack
就好像它是 vector
.这样做可能(并且可能会(违反堆栈的期望(例如,用户可以在中间插入/删除项目,而不是预期的纯粹类似堆栈的方式(。我们基本上使用 vector
作为实现堆栈的便捷方式,但是如果(例如(我们更改了独立stack
实现(不依赖于基类(或根据std::deque
重新实现它,我们不希望这影响任何客户端代码——对于客户端代码,这应该只是一个堆栈, 不是一些专门的矢量(或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 段:
类型为"指向 cvD
的指针"的 prvalue,其中D
是类类型,可以转换为类型为 "指向 cv
B
的指针"的 prvalue,其中 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;
}
- 继承和友元函数,从基类访问受保护的成员
- 如何在复杂继承中访问静态成员变量
- 如何使用 C++ 中的继承函数访问派生类中的局部变量
- 为什么继承的结构成员在联合中无法访问?
- C++继承,无法访问继承的元素
- 构造函数无法访问继承类私有 int
- 重载<<无法访问继承的私有数据
- Qt:如何访问继承的小部件?
- C++无法访问继承类中的字段
- 为什么友元函数无法访问继承类的私有变量?
- 无法访问继承的类属性
- 如何访问继承的成员
- Qt 访问继承类的 D 指针
- 在构造基类期间访问继承的方法
- 当基类要访问继承类的成员时
- 在c++中如何访问继承类中的私有基成员变量
- 访问继承中的私有成员
- 如何在Windows中访问继承的匿名管道HANDLE,而不是stdout,stderr和stdin?
- 使用内部类继承模板类,并访问继承类中的内部类
- 我如何访问继承代码的不同部分