我对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 ++规范)为什么可以在foobar
的{{1}}构造函数中调用函数Bar
}} 尽管有私有继承。
如果我尝试在*this
函数中使用foobar
对象Bar
调用b
函数,则由于私有继承,编译器会按预期给出错误。
我忽略了main
和foobar(*this, 42)
之间的区别是什么?
答案 0 :(得分:2)
这一切都来自foobar
收到Foo
并且不知道Bar
(私有地)继承自Foo
的事实。这个特性由来电者处理:
Bar
的内部构造函数中,为了使用foobar
致电*this
,需要进行转换;具体而言,类型*this
的{{1}}需要转换为Bar
,这是可能的,因为调用者知道两种类型之间的继承关系。< / LI>
Foo&
范围之外的main()
范围内,对class Bar
foobar
b
类型Bar
的调用也需要转换。但在这种情况下,Bar
和Foo
之间的关系是未知的,并且无法进行转换。私有继承意味着只有派生类型知道此继承。在它的范围内,一切都好像是公共继承。但是在派生类型的范围之外,这种关系是未知的,并且一切都发生好像根本没有继承。
答案 1 :(得分:0)
当您私下继承时,您将为派生类将所有基类的公共成员和受保护成员设为私有。因此Bar可以使用自己的私有方法以及其私有基类的公共和受保护方法。但他们的私人仍然无法通过Bar的公共界面访问它们。
14.2 基类的可访问性和基类成员 [class.access.base]
...如果使用私有访问说明符将类声明为另一个类的基类,则基类的公共成员和受保护成员可作为派生类的私有成员访问。
...
应该注意的是,它可以访问受控制的成员和基类,而不是它们的可见性。名称 成员仍然可见,并且当这些成员和基类不可访问时,仍会考虑对基类的隐式转换。建立对给定构造的解释而不考虑 访问控制。如果建立的解释使用了不可访问的成员名称或基类,则该构造是不正确的。
答案 2 :(得分:0)
问题归结为其他问题:私有继承是什么意思?。
这意味着,在简化单词时,除了继承类之外,没有人知道继承发生了。所以直到你的例子 - Bar
知道它是从Foo
派生的,所以在构造函数中没有任何麻烦的向上转换。另一方面,main
不是继承Bar
的一部分,因此无法隐式地将Bar
强制转换为Foo
。