多继承有函数覆盖 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.有覆盖多继承时,子类的虚函数覆盖哪个父类的虚函数,就存在哪个父类的虚表中。(子类虚函数覆盖哪个父类,就在哪个父类的虚表中)。