C ++中的私有继承

时间:2014-01-02 21:08:59

标签: c++ inheritance

在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();
}

};

是否存在任何差异,不允许替换私有继承具有派生类的成员,反之亦然?这是一样的吗?

谢谢!

3 个答案:

答案 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';
}

以上代码将打印3live 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())。