面试题答案
一键面试菱形继承问题描述
菱形继承是指在多重继承体系中,一个派生类从多个直接基类继承,而这些直接基类又继承自同一个间接基类,形成一个菱形结构。例如:
class A {};
class B : public A {};
class C : public A {};
class D : public B, public C {};
这里 D
类通过 B
和 C
间接继承 A
类,形成菱形结构。
不良后果
- 数据冗余:
D
类对象中会存在两份A
类的成员变量,浪费内存空间。 - 访问歧义:当
D
类对象访问A
类成员时,编译器无法确定应使用从B
继承的A
类成员还是从C
继承的A
类成员,导致编译错误。
C++ 解决方案
- 虚继承:使用虚继承可以确保从不同路径继承过来的基类成员在派生类中只有一份实例。
- 接口继承:只继承接口,不继承数据成员,通过组合的方式包含需要的数据成员,避免数据冗余和访问歧义。
虚继承代码示例
#include <iostream>
class A {
public:
int value;
A(int v) : value(v) {}
};
class B : virtual public A {
public:
B(int v) : A(v) {}
};
class C : virtual public A {
public:
C(int v) : A(v) {}
};
class D : public B, public C {
public:
D(int v) : A(v), B(v), C(v) {}
};
int main() {
D d(10);
std::cout << "Value: " << d.value << std::endl;
return 0;
}
虚继承工作原理
虚继承通过在继承关系中使用 virtual
关键字,使得虚基类在派生类对象中只存在一份实例。编译器会为每个使用虚继承的派生类对象添加一个指针(称为虚基表指针),该指针指向一个虚基表,虚基表中记录了虚基类相对于派生类对象的偏移量。当访问虚基类成员时,通过虚基表指针找到虚基表,再根据偏移量定位到虚基类的实例,从而确保无论从哪个路径继承,访问的都是同一个虚基类实例,避免数据冗余和访问歧义。