据我所知,我们无法将派生类对象传递给私有继承的基类引用的原因是,由于Derived是从Base私有继承的,所以Base的默认构造函数将在Derived的构造函数之前调用。但是因为它是私有的而不是继承到Derived,所以我们得到了一个编译器错误。
但是,如果我尝试为Base创建公共构造函数并从Derived私有继承然后将公共状态重新分配给Base的构造函数,它是否允许我将派生的实例传递给Base引用?
我尝试了如下,
#include <iostream>
using namespace std;
class base
{
public:
base(){}
void print(){ puts("In base"); }
};
class derived : private base
{
public:
base::base; /* Throws an error - Declaration doesnt declare anything*/
void print(){ puts("In derived"); }
};
void func(base& bRef)
{
}
int main()
{
derived dObj;
func(dObj); /* Throws an error - 'base' is an inaccessible base of derived */
}
它为base :: base抛出一个错误(将私有继承的构造函数公开给public)。 我有效的是什么?有人可以告诉我吗?
答案 0 :(得分:4)
我们不能对私有继承的派生对象进行基类引用的原因是因为这会违反Liskov Substitution Principle:派生对象IS-NOT-A基类对象,因为它不提供基类公共界面。你无法解决这个问题
出于这个原因,私有继承是一种重用实现的方式,而不是当你想要一个更专业的类型时。因为这可以通过组合完成(即具有基类的成员而不是私有派生),私有继承可能是一个糟糕的代码味道。
您可以阅读here(请务必遵循所有链接),以获取有关私有继承何时是一个不错的选择的更多信息(摘要:当没有其他选择时)。
答案 1 :(得分:2)
不,使用Base类的指针或引用指向Derived的对象是无效的。如果可能的话,那么私有继承的全部目的(隐藏派生类从基类继承其部分(或整体)功能的事实)将毫无用处。
假设你在基类中有一个方法foo()
。您不希望调用此方法。但是如果可以从基类的指针指向对象,那么也可以调用foo()
。
Base * ptrBase = &objDerived; // Let's suppose this would compile
ptrBase->foo(); // Now we can call foo() (?)
当您声明私有继承时,就好像Derived类与基类无关。只有你,开发人员,唯一应该“知道”这种关系存在的人,实际上你应该忘记它,因为它不会起作用。
私有继承仅仅作为可重用性机制,而不是真正的继承机制。建议不要使用它,因为只需应用合成就可以获得更好的结果(即只需在Derived中创建类Base的属性)。