MST

星途 面试题库

面试题:C++多重继承派生新类的菱形继承问题及解决方案

在C++多重继承中,会出现菱形继承问题。请详细描述菱形继承问题是什么,它会带来哪些弊端。然后,说明如何通过虚继承来解决这个问题,包括虚继承的原理、实现方式以及在内存布局上与普通继承有何不同。并给出一个完整的代码示例展示菱形继承及其虚继承解决方案。
44.5万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

菱形继承问题描述

菱形继承是指在多重继承体系中,一个派生类从多个直接基类继承,而这些直接基类又共同继承自同一个基类,形成菱形结构。例如,类D从类B1B2继承,而B1B2又都从类A继承,这种结构就像一个菱形。

菱形继承的弊端

  1. 数据冗余:由于B1B2都继承自A,当D继承B1B2时,D中会存在两份A类的数据成员,造成空间浪费。
  2. 命名冲突:如果A类中有成员函数,D对象在调用这些函数时可能会出现命名冲突,不知道应该调用B1继承来的版本还是B2继承来的版本。

虚继承解决菱形继承问题

  1. 虚继承原理:虚继承的核心思想是让共同的基类(如上述例子中的A)在最终的派生类(如D)中只保留一份数据成员。在虚继承中,虚基类的成员只有一份实例被保留在最终派生类的对象中,而不是像普通继承那样每个直接基类都保留一份。
  2. 实现方式:在继承列表中使用virtual关键字声明虚继承。例如,class B1 : virtual public Aclass B2 : virtual public A。这样,B1B2在继承A时采用虚继承方式。
  3. 内存布局不同:在普通继承中,最终派生类对象内存布局中会有多个来自共同基类的数据成员副本。而在虚继承中,最终派生类对象内存布局中只有一份虚基类的数据成员。通常,虚继承会引入一个虚基类指针,该指针指向虚基类数据成员的存储位置,以实现共享一份数据。

代码示例

#include <iostream>

// 基类A
class A {
public:
    int data;
    A() : data(0) {}
};

// 从A虚继承的类B1
class B1 : virtual public A {
public:
    B1() {}
};

// 从A虚继承的类B2
class B2 : virtual public A {
public:
    B2() {}
};

// 从B1和B2继承的类D
class D : public B1, public B2 {
public:
    D() {
        data = 10; // 此时只有一份data
    }
};

int main() {
    D d;
    std::cout << "d.data: " << d.data << std::endl;
    return 0;
}

上述代码中,D类通过B1B2虚继承自A,保证DA的数据成员data只有一份,避免了菱形继承带来的弊端。