(一)多重继承
多重继承是指由多个基类共同派生出新的派生类的继承结构。这种继承方式能够让派生类融合多个基类的特性,为程序设计带来更大的灵活性。
例如,在描述交通工具的类体系中,我们可以定义FuelEngine类(燃油引擎)和ElectricEngine类(电动引擎):
class FuelEngine
{
private:
int cylinderNum;
public:
FuelEngine(int n = 4) :cylinderNum(n) {}
void Start();
};
class ElectricEngine
{
private:
int power;
public:
ElectricEngine(float p = 60):power(p) {}
void Start();
};
接着,定义HybridCar类(混动汽车)同时继承这两个类,使其具备两种引擎的相关特性:
class HybridCar: public FuelEngine, public ElectricEngine
{
public:
HybridCar() {}
HybridCar(int n, int p){}
};
然而,多重继承虽然强大,但也引入了一些问题,如代码的复杂性增加、潜在的命名冲突等,需要开发者谨慎使用。
(二)菱形继承
菱形继承是多重继承的一种特殊情况。以人员信息管理的类设计为例,Person类作为基类,包含人员的基本信息,如身份证号:
class person
{
private:
int _idPerson;
public:
person(int id) :_idPerson(id) { std::cout << "create person" << std::endl; }
};
student类(学生)和Employee类(教职工)都继承自Person类:
class student : public Person
{
private:
int _snum;
public:
Student(int s, int id) :Person(id), _snum(s) {}
};
class Employee : public Person
{
private:
int _enum;
public:
Employee(int e, int id) :Person(id), _enum(e) {}
};
而EGStudent类(在职研究生)又同时继承自student类和Employee类,形成了菱形继承结构:
class EGStudent : public GStudent, public Employee
{
private:
int _egsnum;
public:
EGStudent(int es, int g, int s, int sid, int e, int eid)
:GStudent(g, s, sid),
Employee(e, eid),
_egsnum(es)
{
}
};
在这种结构中,EGStudent类会继承两份来自Person类的成员(如_idPerson),这就导致了数据冗余和二义性问题。从逻辑上讲,身份证号应该是唯一的,但在物理内存中却分配了不同的空间,变成了两个变量。
(四)虚基类
为了解决菱形继承带来的数据冗余和二义性问题,C++ 引入了虚基类的概念。通过将共同的基类(如Person类)设置为虚基类,从不同路径继承来的同名数据成员在内存中就只有一个拷贝,同名函数也只有一种映射。
定义虚基类的方式如下:
class student : public virtual Person
{
private:
int _snum;
public:
Student(int s, int id) :Person(id), _snum(s) {}
};
class Employee : public virtual Person
{
private:
int _enum;
public:
Employee(int e, int id) :Person(id), _enum(e) {}
};
此时,EGStudent类的定义和构造函数如下:
class EGStudent : public GStudent, public Employee
{
private:
int _egsnum;
public:
EGStudent(int es, int g, int s, int id, int e)
:GStudent(g, s, id),
Employee(e, id),
Person(id),
_egsnum(es)
{
}
};
在虚继承中,派生类对象的构造过程也有所不同。首先是虚基类的构造函数按照声明顺序被调用,接着是非虚基类的构造函数按声明顺序调用,然后是成员对象的构造函数被调用,最后是派生类自己的构造函数被调用。
1.虚基类的底层实现原理
虚基类的底层实现原理主要依靠:虚基类表指针(VBPtr)和虚基类表(VBTbl),当一个类虚继承自某个基类时,编译器会为该派生类对象添加一个额外的指针,称为虚基类表指针(VBPtr)。这个指针指向一个虚基类表(VBTbl)。虚基类表中存储了该派生类对象相对于虚基类对象的偏移量信息。
(五)继承使用建议
虽然 C++ 提供了多重继承和虚基类等强大的机制,但由于菱形继承及其虚继承底层实现较为复杂,可能会导致程序的复杂性增加以及性能问题。
因此,在实际的软件开发中,一般不建议设计出多重继承结构,尤其是菱形继承结构,而是尽量采用更为简洁、清晰的设计方式,以提高代码的可读性、可维护性和性能。
1294

被折叠的 条评论
为什么被折叠?



