在C ++中:假设我有一个类X.私有继承之间有什么区别:
class Deriv : private X
{
public:
//constructor etc
void method()
{
usageOfMethodFromX();
}
};
和此:
class Deriv
{
private:
X * m_xinstance;
public:
//constructor etc
void method()
{
m_xinstance->usageOfMethodFromX();
}
};
是否存在任何差异,不允许替换私有继承具有派生类的成员,反之亦然?这是一样的吗?
谢谢!
答案 0 :(得分:2)
如果基类具有virtual
函数,则存在细微差别:即使基类是私有继承的,也可以重写它:
#include <iostream>
class Base {
virtual int do_f() { return 1; }
public:
int f() { return this->do_f(); }
};
class Derived: Base {
int do_f() { return 2; }
public:
int g() { return this->f(); }
};
class Final: public Derived {
int do_f() { return 3; }
};
int main() {
Final final;
std::cout << final.g() << '\n';
}
以上代码将打印3
(live example)。
代码的另一个不同之处在于,分配内存的方法很好地在堆上分配内存。您可以通过将对象嵌入派生对象来避免此堆分配。
答案 1 :(得分:0)
是
在继承模型中,两个对象的生命周期是交织在一起的。默认情况下会自动连接许多方法(operator=
,构造函数,析构函数),其他方法可能在将来(operator
交换又名:=:
,=default
其他运算符如{ {1}}或<
)。除此之外,==
方法覆盖和调用可以将调用路由到指向父接口的指针(您可以通过调用父方法调用其他方法,或者可以通过调用父方法来调用)。
如果您将virtual
替换为X * m_xinstance
,则将更近替换为相同。生命周期现在已经被束缚了,许多(所有?)的连接方法现在都被类似地连接起来了。 X m_xinstance
行为也非常不同。
最后一个区别是,如果您的基类为空,则可以在一种情况下进行空基类优化,但不能在成员实例中进行。由于不同的对象必须具有不同的地址,因此类的成员的最小大小为virtual
,而空的基类可占用零内存。
答案 2 :(得分:0)
有一个非常明显和明确的区别:考虑这个X
:
class X {
protected:
void doSmth();
};
只有从X
继承的类才能访问任何受保护的成员(此处为X::doSmth()
)。