有了私人继承,什么时候可以上吊?

With private inheritance, when is it ok to upcast?

本文关键字:什么时候 继承      更新时间:2023-10-16

我有一个关于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范围之外,调用foobarb类型为Bar也需要转换。但在这种情况下,BarFoo之间的关系是未知的,并且没有可能的转换。

私有继承意味着只有派生类型知道此继承。在其范围内,一切都像公共继承一样发生。但在派生类型的范围之外,这种关系是未知的,一切都发生得好像根本没有继承一样。

私有继承时,将基类的所有公共和受保护成员设为派生类的私有成员。因此,Bar 可以使用自己的私有方法以及其私有基类的公共和受保护方法。但是他们的隐私仍然,你不能从Bar的公共界面访问他们。

14.2 基类和基类成员的可访问性[class.access.base]
...如果使用专用访问说明符将一个类声明为另一个类的基类,则可以将基类的公共成员和受保护成员作为派生类的私有成员进行
访问。
应该注意的是,控制的是成员和基类的访问,而不是它们的可见性。名字 的成员仍然可见,并且当这些成员和基类不可访问时,仍会考虑对这些基类的隐式转换。对给定结构的解释是在不考虑 存取控制。如果建立的解释使用不可访问的成员名称或基类,则构造格式不正确。

这个问题归结为另一个问题:私有继承是什么意思?简而言之,这意味着除了继承类之外,没有人知道继承发生了。所以直到你的例子 -Bar知道它是从Foo派生的,所以在构造函数中没有问题。另一方面,main不是继承Bar的一部分,因此它不能隐式地将Bar转换为Foo