菱形虚拟继承是单继承和多继承的结合,将类中的函数定义为虚函数。
结合实例看看它的实现过程:
class Animal
{
public:
virtual void Funtest1()
{
cout << "Animal::Funtest1()" << endl;
}
virtual void Funtest2()
{
cout << "Animal::Funtest2()" << endl;
}
private:
int _A;
};
class Donkey :virtual public Animal
{
public:
virtual void Funtest1()
{
cout << "Donkey::Funtest1()" << endl;
}
virtual void Funtest2()
{
cout << "Donkey::Funtest2()" << endl;
}
private:
int _D;
};
class Horse :virtual public Animal
{
public:
virtual void Funtest3()
{
cout << "Horse::Funtest3()" << endl;
}
virtual void Funtest2()
{
cout << "Horse::Funtest2()" << endl;
}
private:
int _D;
};
class Mule:public Donkey,public Horse
{
public:
virtual void Funtest1()
{
cout << "Mule::Funtest1()" << endl;
}
virtual void Funtest2()
{
cout << "Mule::Funtest2()" << endl;
}
virtual void Funtest4()
{
cout << "Mule::Funtest4()" << endl;
}
private:
int _M;
};
void Fun(Animal&A)
{
A.Funtest1();
A.Funtest2();
}
int main()
{
Mule m1;
Fun(m1);
m1.Funtest3();
m1.Funtest4();
system("pause");
return 0;
}
我们来逐个分析一下各个类的模型:
class Animal
{};
class Donkey:public Animal
{};
class Horse:public Animal
{};
class Mule:public Donkey,public Horse
{};
这就是带有虚函数的菱形虚拟继承,并且派生类中有自己的虚函数,上图就是它的结构示意图。
总结:
- (1)当一个类有虚函数时,在其对象的开始会生成一个虚表指针,指向的虚表中会存放虚函数的地址。
- (2)当一个派生类继承一个带有虚函数的基类时,派生类对象成员中基类部分中的虚表指针会被派生类所修改,成为派生类自己的虚表指针。在虚表中,如果虚函数在派生类中被重写那么就会存放被重写过的虚函数指针,如果没有重写基类的虚函数,就会单纯的继承下来存放基类的虚函数指针。
- (3)当一个派生类继承多个带有虚函数的基类时,派生类对象成员中基类部分中的虚表指针会被派生类所修改,成为派生类自己的虚表指针(相当于派生类自己有多个虚表指针)。如果重写了某个基类的虚函数,那么对应的去修改继承于这个基类的成员中的虚表,使指针指向派生类重写过得虚函数,如果没有重写就单纯的继承。