有了私人继承,什么时候可以上吊?
With private inheritance, when is it ok to upcast?
我有一个关于C++的私人继承的问题。 请参阅以下代码示例:
#include <iostream>
class Foo {
public:
virtual void doSomething(int value) {
std::cout << value << std::endl;
}
};
void foobar(Foo& foo, int value) {
foo.doSomething(value);
}
class Bar : Foo {
public:
Bar() {
foobar(*this, 42); // <--- is OK despite private inheritance
}
};
int main() {
Bar b;
foobar(b, 42); // <--- is NOT OK because of private inheritance
}
目前,我无法理解(或找到正确的C++规范)为什么尽管私有继承,Bar
的构造函数foobar
可以在*this
调用。 如果我尝试在main
函数中使用对象b
调用foobar
函数Bar
则由于私有继承,编译器会按预期给出错误。
我忽略的foobar(*this, 42)
和foobar(b, 42)
之间的区别是什么?
这一切都来自这样一个事实,即foobar
接受了Foo
,并且不知道Bar
(私下)继承Foo
的事实。此特征由调用方处理:
- 在
Bar
的构造函数中,为了用*this
调用foobar
,转换是必要的;具体来说,Bar
类型的*this
需要转换为Foo&
,这是可能的,因为调用者知道两种类型之间的继承关系。 - 在
main()
中,在class Bar
范围之外,调用foobar
的b
类型为Bar
也需要转换。但在这种情况下,Bar
和Foo
之间的关系是未知的,并且没有可能的转换。
私有继承意味着只有派生类型知道此继承。在其范围内,一切都像公共继承一样发生。但在派生类型的范围之外,这种关系是未知的,一切都发生得好像根本没有继承一样。
私有继承时,将基类的所有公共和受保护成员设为派生类的私有成员。因此,Bar 可以使用自己的私有方法以及其私有基类的公共和受保护方法。但是他们的隐私仍然,你不能从Bar的公共界面访问他们。
14.2 基类和基类成员的可访问性[class.access.base]
...如果使用专用访问说明符将一个类声明为另一个类的基类,则可以将基类的公共成员和受保护成员作为派生类的私有成员进行
访问。
应该注意的是,控制的是成员和基类的访问,而不是它们的可见性。名字 的成员仍然可见,并且当这些成员和基类不可访问时,仍会考虑对这些基类的隐式转换。对给定结构的解释是在不考虑 存取控制。如果建立的解释使用不可访问的成员名称或基类,则构造格式不正确。
这个问题归结为另一个问题:私有继承是什么意思?简而言之,这意味着除了继承类之外,没有人知道继承发生了。所以直到你的例子 -Bar
知道它是从Foo
派生的,所以在构造函数中没有问题。另一方面,main
不是继承Bar
的一部分,因此它不能隐式地将Bar
转换为Foo
。
- 什么时候调用组成单元对象的析构函数
- 什么时候在C++中返回常量引用是个好主意
- 什么时候调用析构函数
- boost odeint什么时候真正调用观测者
- 编译器对数组声明大小的计算。什么时候发生?
- 什么时候最好在子进程中使用 CPU 或 I/O 密集型代码 [ C++ ]
- 您应该在什么时候创建自己的异常类型
- 我什么时候会默认(而不是删除)基类中的复制和移动操作
- 什么时候可以使用常量装饰调用我的重载函数?
- unordered_map什么时候返回 -1?
- QCoreApplication什么时候有效?
- sizeof(size_t) 和 sizeof(ptrdiff_t) 什么时候会有所不同?
- 什么时候用指针调用C++类构造函数
- 我不明白在这个例子中什么时候调用构造函数
- 如果真的需要std::move,我们应该什么时候声明右值refs
- P1008("prohibit aggregates with user-declared constructors")在实践中什么时候有用?
- 有了私人继承,什么时候可以上吊?
- 什么时候使用友元类/函数而不是继承
- 我什么时候可以安全地从C++中的基类继承
- 什么时候应该使用模板而不是继承,反之亦然