多继承有函数覆盖
struct Base1
{
public:
virtual void Fn_1()
{
printf("Base1:Fn_1...\n");
}
virtual void Fn_2()
{
printf("Base1:Fn_2...\n");
}
};
struct Base2
{
public:
virtual void Fn_3()
{
printf("Base2:Fn_3...\n");
}
virtual void Fn_4()
{
printf("Base2:Fn_4...\n");
}
};
struct Sub:Base1,Base2
{
public:
virtual void Fn_1()
{
printf("Sub:Fn_1...\n");
}
virtual void Fn_3()
{
printf("Sub:Fn_3...\n");
}
virtual void Fn_5()
{
printf("Sub:Fn_5...\n");
}
};
int main(int argc, char* argv[])
{
//查看 Sub 的虚函数表
Sub sub;
//通过函数指针调用函数,验证正确性
typedef void(*pFunction)(void);
//对象的前四个字节是第一个Base1的虚表
printf("Sub 的虚函数表地址为:%x\n",*(int*)&sub);
pFunction pFn;
for(int i=0;i<6;i++)
{
int temp = *((int*)(*(int*)&sub)+i);
if(temp == 0)
{
break;
}
pFn = (pFunction)temp;
pFn();
}
//对象的第二个四字节是Base2的虚表
printf("Sub 的虚函数表地址为:%x\n",*(int*)((int)&sub+4));
pFunction pFn1;
for(int k=0;k<2;k++)
{
int temp = *((int*)(*(int*)((int)&sub+4))+k);
pFn1 = (pFunction)temp;
pFn1();
}
return 0;
}
上面示例代码中,子类sub的sub:Fn_1、sub:Fn_3、sub:Fn_5,与父类base1、base2,先覆盖,后继承,也就是说编译器第一步,会先用子类和所有的父类的比较,有相同的就会把子类虚函数覆盖到父类虚表中。第二步,注意,不相同的子类虚函数会贴在第一个父类虚表后面的位置。
1.平时不建议使用多继承,代码的维护会比较麻烦,尽量使用多重继承。
2.多继承有时,除了子类继承第一个父类虚表外,其它继承过来的父类都会单独有一张虚表,也就是虚表会有多个。
3.有覆盖多继承时,子类的虚函数覆盖哪个父类的虚函数,就存在哪个父类的虚表中。(子类虚函数覆盖哪个父类,就在哪个父类的虚表中)。