C++之 虚继承

目录

菱形继承的问题:

解决方案--虚继承

注意


菱形继承的问题:

菱形继承指的是一个派生类从两个中间基类继承,而这两个中间基类又都继承自同一个基类。这样会造成派生类中存在两份基类的数据副本,容易引发数据冗余和二义性问题。

下面是一个菱形继承的示例代码:

#include 

// 基类
class Base {
public:
    int data;
};

// 中间基类1
class Derived1 : public Base {};

// 中间基类2
class Derived2 : public Base {};

// 最终派生类
class FinalDerived : public Derived1, public Derived2 {};

int main() {
    FinalDerived obj;
    // 这里会产生二义性,因为不知道是访问Derived1::data还是Derived2::data
    // obj.data = 10; 

    // 必须明确指定访问路径
    obj.Derived1::data = 10;
    obj.Derived2::data = 20;

    std::cout << "Derived1::data: " << obj.Derived1::data << std::endl;
    std::cout << "Derived2::data: " << obj.Derived2::data << std::endl;

    return 0;
}

在上述代码中,FinalDerived类继承自Derived1Derived2,而Derived1Derived2又都继承自Base。这就使得FinalDerived类中存在两份Base类的数据副本,在访问data成员时会产生二义性。

解决方案--虚继承

虚继承能够确保在菱形继承结构里,最终派生类中仅存在一份基类的数据副本,从而避免数据冗余和二义性问题。

以下是使用虚继承解决菱形继承问题的示例代码:

#include 

// 基类
class Base {
public:
    int data;
};

// 中间基类1,使用虚继承
class Derived1 : virtual public Base {};

// 中间基类2,使用虚继承
class Derived2 : virtual public Base {};

// 最终派生类
class FinalDerived : public Derived1, public Derived2 {};

int main() {
    FinalDerived obj;
    // 现在可以直接访问data成员,不会产生二义性
    obj.data = 10;

    std::cout << "data: " << obj.data << std::endl;

    return 0;
}

在这个例子中,Derived1Derived2使用了虚继承virtual public Base。这样,FinalDerived类中就只有一份Base类的数据副本,访问data成员时不会产生二义性。

注意

  • 虚继承是解决菱形继承问题的有效手段,它能保证最终派生类中只有一份基类的数据副本。
  • 不过,虚继承也会增加一定的开销,因为需要额外的指针来维护虚基类表。
  • 所以,只有在确实需要解决菱形继承问题时才使用虚继承。 

未完待续。。。 

你可能感兴趣的:(c++,C++)