什么是 C++ 中的多继承?它有哪些优缺点? 什么是虚继承?为什么要使用虚继承?

1)什么是 C++ 中的多继承?它有哪些优缺点?

一、多继承的定义

在 C++中,多继承是指一个类可以从多个基类继承成员。

例如:

class Base1 {
public:
    void func1() {
        //...
    }
};

class Base2 {
public:
    void func2() {
        //...
    }
};

class Derived : public Base1, public Base2 {
};

在这个例子中, Derived 类同时继承了 Base1 和 Base2 两个类。

二、多继承的优点

1. 代码复用性高

可以从多个不同的类中继承功能,避免重复编写代码。

例如,一个图形绘制程序中,可能有一个表示形状的基类和一个表示颜色的基类,通过多继承可以创建一个既具有形状属性又具有颜色属性的具体图形类。

2. 灵活性强

可以根据具体需求组合不同的基类功能,实现更加复杂的类层次结构。

比如,一个游戏角色类可以同时继承表示移动能力的基类、表示攻击能力的基类和表示生命值管理的基类等。

三、多继承的缺点

1. 二义性问题

当多个基类中存在同名成员时,在派生类中访问该成员可能会产生二义性。例如:

class Base1 {
public:
    int value;
};

class Base2 {
public:
    int value;
};

class Derived : public Base1, public Base2 {
public:
    void printValue() {
        // 这里访问 value 会产生二义性
        std::cout << value << std::endl;
    }
};

解决二义性需要使用作用域解析运算符明确指定访问哪个基类的成员。

2. 复杂性增加

多继承使得类的层次结构变得更加复杂,难以理解和维护。特别是当继承层次较深时,可能会导致代码的可读性和可维护性降低。

3. 菱形继承问题

多继承可能导致菱形继承问题,即两个派生类继承同一个基类,然后又有一个类同时继承这两个派生类。这可能会导致在派生类中存在多份基类的子对象,浪费内存空间并且可能引发二义性问题。可以通过虚继承来解决菱形继承问题,但这又增加了代码的复杂性。

2) 什么是虚继承?为什么要使用虚继承?

一、虚继承的定义

在 C++中,虚继承是一种继承方式,用于解决多继承时可能出现的重复继承同一个基类的问题。

当一个类以虚继承的方式继承基类时,在派生类的对象布局中,只会存在一份基类的子对象,而无论有多少条继承路径指向该基类。

例如:

class Base {
public:
    int data;
};

class Derived1 : virtual public Base {
};

class Derived2 : virtual public Base {
};

class MostDerived : public Derived1, public Derived2 {
};

 在这个例子中, MostDerived 类通过 Derived1 和 Derived2 间接虚继承了 Base 类,在 MostDerived 类的对象中只会有一份 Base 类的子对象。

二、使用虚继承的原因

1. 避免二义性

在多继承中,如果多个基类中有同名成员,且没有使用虚继承,那么在派生类中访问该成员时可能会产生二义性。而通过虚继承,派生类对象中只有一份基类的子对象,避免了这种二义性。

class Base {
public:
    int value;
};

class Derived1 : public Base {
};

class Derived2 : public Base {
};

class MostDerived : public Derived1, public Derived2 {
public:
    void printValue() {
        // 如果没有虚继承,这里访问 value 会产生二义性
        std::cout << value << std::endl;
    }
};

 2. 节省内存空间

当存在复杂的继承层次结构时,如果不使用虚继承,可能会导致多个基类子对象在派生类对象中重复存储,浪费内存空间。而虚继承可以确保只存在一份基类子对象,节省内存。

虚继承在 C++中是一种解决多继承问题的重要手段,可以避免二义性和节省内存空间。

3.解决菱形继承问题

继承

class A
{
public:
	int a;
};
class B :public A
{
public:
	int b;
};
class C :public A
{
public:
	int c;
};
class D :public B, public C
{
public:
	int d;
};

int main()
{
	D d;
	d.a;
	return 0;
}

非虚继承会出现下图状况产生菱形继承二义性D::a不明确

虚继承,D中的内存情况

虚继承

class A
{
public:
	int a;
};
class B :virtual public A
{
public:
	int b;
};
class C :virtual public A
{
public:
	int c;
};
class D :public B, public C
{
public:
	int d;
};

int main()
{
	D d;
	d.a;
	return 0;
}

使用虚继承解决了菱形继承问题

虚继承D中的内存情况

4.虚继承原理

虚继承定义一个虚基表指针vbptr,指向虚基表而虚基表中会存在偏移量,这个量就是表的地址到父类数据地址的距离

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值