//直接来个复杂的多重继承#include <stdio.h>class Base{public: Base(){ puts("Base()"); } virtual void fun1() { puts("Base::fun1()"); } virtual void fun2() { puts("Base::fun2()"); } virtual void fun3() { puts("Base::fun3()"); } void fun4(){ printf("Normal Base::fun4()\n"); } ~Base(){ puts("~Base()"); }};class Base2{public: Base2(){ puts("Base2()"); } virtual void foo1(){ puts("Base2::foo1()"); } virtual void foo2(){ puts("Base2::foo2()"); } ~Base2(){ puts("~Base2()"); }};class Base3{public: Base3(){ puts("Base3()"); } virtual void bar1(){ puts("Base3::bar1()"); } ~Base3(){ puts("~Base3()"); }};class Derive : public Base,public Base2,public Base3{public: Derive() { puts("Derive()"); } void fun1() { puts("Derive::fun1()"); } void fun2() { puts("Derive::fun2()"); } void foo1() { puts("Derive::foo1()"); }/* void fun3() { puts("Derive::fun3()"); } */ void fun4(){ printf("Normal Derive::fun4()\n"); } ~Derive(){ puts("~Derive()"); }};typedef void (*FUN) (void);int main(){ FUN pfun1 = NULL; FUN pfun2 = NULL; FUN pfun3 = NULL; FUN pfun4 = NULL; FUN pfun5 = NULL; FUN pfun6 = NULL; Base * pb = NULL; Base2 *pb2 = NULL; Base3 *pb3 = NULL; Derive b; printf("sizeof b = %d\n",sizeof b); printf("&b = %p\n",(&b)); printf("vtable = %p\n",(int *)(&b)); printf("*vtable = %p\n",**(int **)(&b)); printf("b = %p\n",*(int*)(&b)); //使用两种情况调用比对 /* pb = &b; pb->fun1(); pb->fun2(); pb->fun3(); pb2 = &b; pb2->foo1(); pb2->foo2(); pb3 = &b; pb3->bar1();*/ pfun1 = (FUN)**(int**)(&b); pfun1(); pfun2 = (FUN)*(*(int**)(&b)+1); pfun2(); pfun3 = (FUN)*(*(int**)(&b)+2); pfun3(); pfun4 = (FUN)*(*((int**)(&b)+1)); pfun4(); pfun5 = (FUN)*(*((int**)(&b)+1)+1); pfun5(); pfun6 = (FUN)*(*((int**)(&b)+2)); pfun6(); return 0;}/*Base()Base2()Base3()Derive()sizeof b = 12 //保存三个虚函数表的地址 &b = 0xbfecb770vtable = 0xbfecb770*vtable = 0x80488fab = 0x8048be8Derive::fun1()Derive::fun2()Base::fun3()Derive::foo1()Base2::foo2()Base3::bar1()~Derive()~Base3()~Base2()~Base()汇编的代码很长但是关键的地方在Derive的构造函数,这里只给出最关键的几行...call_ZN5Base3C2Ev.LEHE2:movl8(%ebp), %eax #this 下面是对 b的12个字节赋值movl$_ZTV6Derive+8, (%eax) #vtable1 movl8(%ebp), %eaxmovl$_ZTV6Derive+32, 4(%eax) #vtable2movl8(%ebp), %eaxmovl$_ZTV6Derive+48, 8(%eax) #vtable3movl$.LC12, (%esp)....globl main.typemain, @functionmain:...leal16(%esp), %eax #this 即指向vtables的指针movl(%eax), %eax #vtable1movl(%eax), %eax #_ZN6Derive4fun1Ev Derive::fun1()movl%eax, 28(%esp)movl28(%esp), %eaxcall*%eaxleal16(%esp), %eax #thismovl(%eax), %eaxaddl$4, %eax #_ZN6Derive4fun2Ev Derive::fun2()movl(%eax), %eaxmovl%eax, 32(%esp)movl32(%esp), %eaxcall*%eaxleal16(%esp), %eaxmovl(%eax), %eaxaddl$8, %eaxmovl(%eax), %eaxmovl%eax, 36(%esp)movl36(%esp), %eaxcall*%eaxleal16(%esp), %eax #this 即指向vtables的指针addl$4, %eax #eax 保存vtable2的地址movl(%eax), %eax #eax 解引用得到vtable2movl(%eax), %eax #eax _ZThn4_N6Derive4foo1Ev movl%eax, 40(%esp)movl40(%esp), %eaxcall*%eaxleal16(%esp), %eaxaddl$4, %eaxmovl(%eax), %eaxaddl$4, %eaxmovl(%eax), %eax #_ZN5Base24foo2Evmovl%eax, 44(%esp)movl44(%esp), %eaxcall*%eaxleal16(%esp), %eax #this 即指向vtables的指针addl$8, %eax #eax 保存vtable3的地址movl(%eax), %eax #eax 解引用得到vtable3movl(%eax), %eax #_ZN5Base34bar1Ev movl%eax, 48(%esp)movl48(%esp), %eaxcall*%eax....size_ZTV6Derive, 52_ZTV6Derive:.long0.long_ZTI6Derive.long_ZN6Derive4fun1Ev #vtable1 _ZTV6Derive+8.long_ZN6Derive4fun2Ev.long_ZN4Base4fun3Ev.long_ZN6Derive4foo1Ev.long-4.long_ZTI6Derive.long_ZThn4_N6Derive4foo1Ev #vtable2 _ZTV6Derive+32.long_ZN5Base24foo2Ev .long-8.long_ZTI6Derive.long_ZN5Base34bar1Ev #vtable3 _ZTV6Derive+48...使用注释部分调用的汇编代码是:...movl$0, 52(%esp) #Base * pb = NULL;movl$0, 56(%esp) #Base2 *pb2 = NULL;movl$0, 60(%esp) #Base3 *pb3 = NULL;...leal16(%esp), %eaxmovl%eax, 52(%esp) #(%eax)即保存地址 $_ZTV6Derive+8, #vtable1 pb1 = &b;leal16(%esp), %eaxaddl$4, %eax # 4(%eax)即保存地址 $_ZTV6Derive+32, #vtable2movl%eax, 56(%esp) # pb3 = &b; leal16(%esp), %eaxaddl$8, %eax # 8(%eax)即保存地址 $_ZTV6Derive+48, #vtable3 movl%eax, 60(%esp) # pb3 = &b; #基类指针只保存对应的经过子类调整(是否重定义虚函数)虚函数表... movl52(%esp), %eax #pb 中保存vtable1虚表movl(%eax), %eaxmovl(%eax), %edxmovl52(%esp), %eaxmovl%eax, (%esp) #将this保存到栈中,这就是多态时隐式传递的this指针指向子类的 在上面的调用中没有这一步this指针隐式传参call*%edx #pb->fun1(); movl52(%esp), %eaxmovl(%eax), %eaxaddl$4, %eax #获得_ZN6Derive4fun2Ev 的地址movl(%eax), %edx #得到_ZN6Derive4fun2Ev函数地址movl52(%esp), %eaxmovl%eax, (%esp)call*%edx #pb->fun2();movl52(%esp), %eaxmovl(%eax), %eaxaddl$8, %eaxmovl(%eax), %edxmovl52(%esp), %eaxmovl%eax, (%esp)call*%edx #pb->fun3(); movl56(%esp), %eax #pb2movl(%eax), %eaxmovl(%eax), %edxmovl56(%esp), %eaxmovl%eax, (%esp)call*%edx # pb2->foo1();movl56(%esp), %eaxmovl(%eax), %eaxaddl$4, %eaxmovl(%eax), %edxmovl56(%esp), %eaxmovl%eax, (%esp)call*%edx #pb2->foo2();movl60(%esp), %eax #pb3movl(%eax), %eaxmovl(%eax), %edxmovl60(%esp), %eaxmovl%eax, (%esp)call*%edx #pb3->bar1();*/