测试三:多重继承(带虚函数)
3.1、普通多重继承,带虚函数,自己有新增虚函数
#pragma vtordisp(off)
#include <iostream>
using std::cout;
using std::endl;
class Base1
{
public:
Base1() : _iBase1(10) {}
virtual void f()
{
cout << "Base1::f()" << endl;
}
virtual void g()
{
cout << "Base1::g()" << endl;
}
virtual void h()
{
cout << "Base1::h()" << endl;
}
private:
int _iBase1;
};
class Base2
{
public:
Base2() : _iBase2(100) {}
virtual void f()
{
cout << "Base2::f()" << endl;
}
virtual void g()
{
cout << "Base2::g()" << endl;
}
virtual void h()
{
cout << "Base2::h()" << endl;
}
private:
int _iBase2;
};
class Base3
{
public:
Base3() : _iBase3(1000) {}
virtual void f()
{
cout << "Base3::f()" << endl;
}
virtual void g()
{
cout << "Base3::g()" << endl;
}
virtual void h()
{
cout << "Base3::h()" << endl;
}
private:
int _iBase3;
};
class Derived
: /*virtual*/ public Base1
, /*virtual*/ public Base2
, /*virtual*/ public Base3
{
public:
Derived() : _iDerived(10000) {}
void f()
{
cout << "Derived::f()" << endl;
}
virtual void g1()
{
cout << "Derived::g1()" << endl;
}
private:
int _iDerived;
};
int main(void)
{
Derived d;
return 0;
}
内存布局:
非虚继承,基类的内存布局在前,派生类的在后,自己没有新增虚函数指针,都是继承过来的,新增的虚函数放在继承过来的第一张虚表里,加快查找速度
3.2、虚拟多重继承,带虚函数,自己有新增虚函数(只有第一个是虚继承)
class Derived
: virtual public Base1
, /*virtual*/ public Base2
, /*virtual*/ public Base3
{
public:
Derived() : _iDerived(10000) {}
void f()
{
cout << "Derived::f()" << endl;
}
virtual void g1()
{
cout << "Derived::g1()" << endl;
}
private:
int _iDerived;
};
内存布局:
虚拟继承,新增一个虚基指针,虚基类的内存布局放在最后
3.3、虚拟多重继承,带虚函数,自己有新增虚函数(三个都是虚继承)
class Derived
: virtual public Base1
, virtual public Base2
, virtual public Base3
{
public:
Derived() : _iDerived(10000) {}
void f()
{
cout << "Derived::f()" << endl;
}
virtual void g1()
{
cout << "Derived::g1()" << endl;
}
private:
int _iDerived;
};
内存布局:
总结:
1、不管派生类有没有新增虚函数表,派生类新增的虚函数都放在第一个虚函数表中(可能是继承过来的,也可能是自己新建的,就近原则),加快查找速度
2、派生类会覆盖基类的虚函数,只有第一个从基类继承过来的虚函数表中存放的是真实的被覆盖的虚函数的地址,其它的虚函数表中存放的并不是真实的对应的虚函数的地址,而只是一条跳转指令
3、内存布局:①非虚继承的基类内存布局优先
②派生类内存布局(包括虚基指针和数据成员)在虚基类内存布局之前,通过虚基指针找到虚基类的内存布局,所以虚基类的内存布局放在派生类内存布局之后
4、当继承类型都是虚拟继承时,派生类新增虚函数的话,会新增自己的虚函数指针和虚函数表,新增的虚函数表存放新增虚函数入口地址,位于内存布局的最前面,加快访问速度(时间换空间)