多继承

本文深入探讨了C++中的多继承概念,包括其语法和实例演示。特别关注了多继承的一种特殊情况——菱形继承,分析了其带来的数据冗余和二义性问题,并介绍了虚拟继承作为解决方案的原理和应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

多继承
之前在https://blog.youkuaiyun.com/Jochebed666/article/details/86571445博客中主要提到了单继承,那么什么是多继承呢???

多继承即一个子类可以有多个父类,它继承了多个父类的特性。
C++ 类可以从多个类继承成员,语法如下:

class <派生类名>:<继承方式1><基类名1>,<继承方式2><基类名2>,…
{
<派生类类体>
};

其中,访问修饰符继承方式是 public、protected 或 private 其中的一个,用来修饰每个基类,各个基类之间用逗号分隔,如上所示。现在让我们一起看看下面的实例:

#include <iostream>
using namespace std;
 
// 基类 Shape
class Shape 
{
   public:
      void setWidth(int w)
      {
         width = w;
      }
      void setHeight(int h)
      {
         height = h;
      }
   protected:
      int width;
      int height;
};
 
// 基类 PaintCost
class PaintCost 
{
   public:
      int getCost(int area)
      {
         return area * 70;
      }
};
 
// 派生类
class Rectangle: public Shape, public PaintCost
{
   public:
      int getArea()
      { 
         return (width * height); 
      }
};
 
int main(void)
{
   Rectangle Rect;
   int area;
 
   Rect.setWidth(5);
   Rect.setHeight(7);
 
   area = Rect.getArea();
   
   // 输出对象的面积
   cout << "Total area: " << Rect.getArea() << endl;
 
   // 输出总花费
   cout << "Total paint cost: $" << Rect.getCost(area) << endl;
 
   return 0;
}

当上面的代码被编译和执行时,它会产生下列结果:

Total area: 35
Total paint cost: $2450

我们可以发现多继承跟单继承在很多地方很相似。这就是比单继承多了些父类。而多继承里有一种特殊的继承方式叫菱形继承。

菱形继承
菱形继承是多继承的一种特殊情况。
菱形继承的问题:从下面的对象成员模型构造,可以看出菱形继承有数据冗余和二义性的问题。在Assistant的对象中Person成员会有两份。

#include<iostream>
#include<string>
using namespace std;

class Person
{
public:
	string _name ; // 姓名
};
class Student : public Person
{
protected :
	int _num ; //学号
};
class Teacher : public Person
{
protected :
	int _id ; // 职工编号
};
class Assistant : public Student, public Teacher
{
protected :
	string _majorCourse ; // 主修课程
};
int main()
{
	// 这样会有二义性无法明确知道访问的是哪一个
	Assistant a ;
	a._name = "peter";
	// 需要显示指定访问哪个父类的成员可以解决二义性问题,但是数据冗余问题无法解决
	a.Student::_name = "xxx";
	a.Teacher::_name = "yyy";
	
	return 0;
}

菱形继承
从图中我们看到菱形继承有数据冗余的现象一个Assistant将会有两个Person,且两个Person的位置不一致,所以当改变Person其中之一,其他的Person也随之改变。
那么如何解决菱形继承的二义性和数据冗余呢???
c++中提供了虚拟继承来解决这个问题。即继承Person时使用虚拟继承。

class <派生类名>:virtual <继承方式> <基类名>
{
<派生类类体>
};

虚拟继承的原理主要是生成一个基类的偏移量,通过偏移量查找唯一的基类值,即:

class Person
{
public :
 string _name ; // 姓名
};
class Student : virtual public Person
{
protected :
 int _num ; //学号
};
class Teacher : virtual public Person
{
protected :
 int _id ; // 职工编号
};
class Assistant : public Student, public Teacher
{
protected :
 string _majorCourse ; // 主修课程
};
void Test ()
{
 Assistant a ;
 a._name = "peter";
}

菱形虚拟继承
从图中我们看到虚拟继承是通过了Student和Teacher的两个指针,指向的一张表。这两个指针叫虚基表指针,这两个表叫虚基表。虚基表中存了偏移量。通过偏移量可以找到下面的Person。虚拟继承使用偏移量,所以有消耗,当基类比较大时,可节约空间消耗,但效率有所下降。

小结一下
多继承是c++的一个缺陷。特别是会出现菱形继承和菱形虚拟继承,底层实现复杂!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值