多重继承多态的实现
来源:互联网 发布:sem优化方案模板 编辑:程序博客网 时间:2024/06/10 00:24
关于C++的虚表以及C++对象的内存布局,这两篇blog写的不错:
C++虚函数表解析
http://blog.csdn.net/haoel/archive/2007/12/18/1948051.aspx
C++对象的内存布局(上)
http://blog.csdn.net/haoel/archive/2008/10/15/3081328.aspx
C++对象的内存布局(下)
http://blog.csdn.net/haoel/archive/2008/10/15/3081385.aspx
单重继承虚函数实现多态的机制比较简单,从对象首地址取虚表指针就可以从虚表动态访问到相应的虚函数,但多重继承有多个父类的虚表指针,怎么实现动态绑定呢?
借用上面几篇blog中的例子:
还有一点不太明白,编译器怎么看到这句Base2 *pb2 = &d;就知道指针要向后偏移呢,编译器并不知道指向的是一个Derive类的对象,根据继承关系吗?不太明白,还请知道的指点一下!
C++虚函数表解析
http://blog.csdn.net/haoel/archive/2007/12/18/1948051.aspx
C++对象的内存布局(上)
http://blog.csdn.net/haoel/archive/2008/10/15/3081328.aspx
C++对象的内存布局(下)
http://blog.csdn.net/haoel/archive/2008/10/15/3081385.aspx
单重继承虚函数实现多态的机制比较简单,从对象首地址取虚表指针就可以从虚表动态访问到相应的虚函数,但多重继承有多个父类的虚表指针,怎么实现动态绑定呢?
借用上面几篇blog中的例子:
- class Base1
- {
- public:
- int ibase1;
- Base1():ibase1(10) {}
- virtual void f() { cout << "Base1::f()" << endl; }
- virtual void g() { cout << "Base1::g()" << endl; }
- virtual void h() { cout << "Base1::h()" << endl; }
- };
- class Base2
- {
- public:
- int ibase2;
- Base2():ibase2(20) {}
- virtual void f() { cout << "Base2::f()" << endl; }
- virtual void g() { cout << "Base2::g()" << endl; }
- virtual void h() { cout << "Base2::h()" << endl; }
- };
- class Base3
- {
- public:
- int ibase3;
- Base3():ibase3(30) {}
- virtual void f() { cout << "Base3::f()" << endl; }
- virtual void g() { cout << "Base3::g()" << endl; }
- virtual void h() { cout << "Base3::h()" << endl; }
- };
- class Derive : public Base1, public Base2, public Base3
- {
- public:
- int iderive;
- Derive():iderive(100) {}
- virtual void f() { cout << "Derive::f()" << endl; }
- virtual void g1() { cout << "Derive::g1()" << endl; }
- };
- Derive d;
- Base1 *pb1 = &d;
- 00411C36 lea eax,[ebp-0D8h]
- 00411C3C mov dword ptr [ebp-0F0h],eax
- Base2 *pb2 = &d;
- //原来指针赋值时编译器就做了手脚
- 00411C42 lea eax,[ebp-0D8h] ;取对象d的地址
- 00411C48 test eax,eax ;判断地址是否为0
- 00411C4A je main+2EAh (411C5Ah)
- 00411C4C lea ecx,[ebp-0D0h] ;这里地址向后偏移了8
- 00411C52 mov dword ptr [ebp-5B4h],ecx
- 00411C58 jmp main+2F4h (411C64h)
- 00411C5A mov dword ptr [ebp-5B4h],0
- 00411C64 mov edx,dword ptr [ebp-5B4h]
- 00411C6A mov dword ptr [ebp-0FCh],edx ;偏移后的地址送往pb2
- Base3 *pb3 = &d;
- pb1->f(); // Derive::f(),实现了动态绑定
- //看下汇编代码,vs2005
- 00411C9E mov eax,dword ptr [ebp-0F0h] eax:0x0012fe90(d的起始地址)
- 00411CA4 mov edx,dword ptr [eax]
- 00411CA6 mov esi,esp
- 00411CA8 mov ecx,dword ptr [ebp-0F0h]
- 00411CAE mov eax,dword ptr [edx]
- 00411CB0 call eax
- pb2->f(); // Derive::f(),汇编代码跟pb1->f()差不多,那怎么定位到Derive中Base2的虚表呢,发现这里pb2的值已经不再指向d的首地址了,而是偏移了Base1对象的大小,这样就可以找到正确的虚指针了,看下上面的赋值语句,看看编译器是怎么做的
- 00411CB9 mov eax,dword ptr [ebp-0FCh] eax:0x0012fe98(偏移了Base1的大小8)
- 00411CBF mov edx,dword ptr [eax]
- 00411CC1 mov esi,esp
- 00411CC3 mov ecx,dword ptr [ebp-0FCh]
- 00411CC9 mov eax,dword ptr [edx]
- 00411CCB call eax
- pb3->f(); // Derive::f()
- pb1->g(); // Base1::g()
- pb2->g(); // Base1::g()
- pb3->g(); // Base1::g()
- 多重继承多态的实现
- 实现类和继承、多重继承和多态
- python的多重继承与多态
- Java 利接口来实现多态的情况, 和利用接口实现多重继承!
- lua 多重继承的实现在
- js实现多重继承的例子
- lua 多重继承的实现在
- 实现c++类的多重继承
- Lua中多重继承的简单实现
- java实现多重继承
- 实现多重继承
- java 实现多重继承
- java实现多重继承
- 实现多重继承
- java实现多重继承
- JAVA实现多重继承
- 运行时的多态与多重继承
- 0015.scala的多重继承、多重继承构造器执行顺序、基于trait的AOP实现
- CHtmlView的通信机制
- func5-1.cpp && bo5-1~bo5-6.cpp s 数组和广义表 算法
- 常见网络攻击(转)
- 运行QQ提示找不到SVHUVS.DLL?一些安全网站打不开?修复~
- 长庆油田银川实训系统开发
- 多重继承多态的实现
- 常见问题
- B2C网站兼职开发
- B2C网站兼职开发
- ABAP负号提前
- algo5-1~algo5-2.cpp 数组和广义表 主程序
- 女人嫁人的经典准则
- main5-1~main5-6.cpp 数组和广义表 检验算法的主程序
- spring与struts整合