用派生类的指针调用基类的函数为什么也可以实现多态?该怎么处理
用派生类的指针调用基类的函数为什么也可以实现多态?
结果:
A::h()
B::f()
A::g()
最近在学习C++的虚函数,书上说要用基类的指针或引用才能实现多态。但上述代码,p是子类的,调用派生来的h(),this指针也是指向B类的,this->f()
假如说,只是简单的调用自己的f()(不是通过虚函数)。那么下一句,this->g()也应当是简单的调用自己的g(),输出是B::f()啊。
或者,派生类的指针调用基类的函数,而此函数中又调用虚函数,也可以实现多态(好像就基类的构造函数不可以)。那么就,当调用h()时候,作用域已经变成A::,此函数体中的调用也都是在A::的作用域中,因为有多态,F()调用的是子类中的,而,g()仍在A::中,调用的是A::中的g()。如果这样解释的话应该好些。
于是就很矛盾了,第一次提问,还请大家多多指教,还有没有多少积分,给不了多少,见谅,呵呵 ^^
------解决方案--------------------
正确答案来啦
首先 对象B 有一个虚函数表vftable 保存了 A B继承体系中唯一一个虚函数f,且表中唯一一项也是第一项就是B::f()地址
那么不管用什么指针,只要指向的对象是B的 再调用f函数时就会选择B本身的虚函数表第一项,就是调用B::f 啦
然后 打印A::h() 很明显,B没有重载这个函数,肯定要走入A::h() 查看h方法反汇编如下,
看到下面一行 就知道,再h中嗲用g编译器已经事先写死了 就是调用A的g方法
call A::g (4157FDh)
综上 疑问解决
- C/C++ code
#include<iostream.h> class A { public: virtual void f() {cout<<"A::f()"<<endl;} void g() {cout<<"A::g()"<<endl;} void h() { cout<<"A::h()"<<endl; f(); g(); } }; class B: public A { public: void f() {cout<<"B::f()"<<endl;} void g() {cout<<"B::g()"<<endl;} }; void main() { B b; B * p=&b; p->h(); }
结果:
A::h()
B::f()
A::g()
最近在学习C++的虚函数,书上说要用基类的指针或引用才能实现多态。但上述代码,p是子类的,调用派生来的h(),this指针也是指向B类的,this->f()
假如说,只是简单的调用自己的f()(不是通过虚函数)。那么下一句,this->g()也应当是简单的调用自己的g(),输出是B::f()啊。
或者,派生类的指针调用基类的函数,而此函数中又调用虚函数,也可以实现多态(好像就基类的构造函数不可以)。那么就,当调用h()时候,作用域已经变成A::,此函数体中的调用也都是在A::的作用域中,因为有多态,F()调用的是子类中的,而,g()仍在A::中,调用的是A::中的g()。如果这样解释的话应该好些。
于是就很矛盾了,第一次提问,还请大家多多指教,还有没有多少积分,给不了多少,见谅,呵呵 ^^
------解决方案--------------------
正确答案来啦
首先 对象B 有一个虚函数表vftable 保存了 A B继承体系中唯一一个虚函数f,且表中唯一一项也是第一项就是B::f()地址
那么不管用什么指针,只要指向的对象是B的 再调用f函数时就会选择B本身的虚函数表第一项,就是调用B::f 啦
然后 打印A::h() 很明显,B没有重载这个函数,肯定要走入A::h() 查看h方法反汇编如下,
看到下面一行 就知道,再h中嗲用g编译器已经事先写死了 就是调用A的g方法
call A::g (4157FDh)
综上 疑问解决
- Assembly code
f(); g(); 00416E41 mov eax,dword ptr [this] 00416E44 mov edx,dword ptr [eax] 00416E46 mov esi,esp 00416E48 mov ecx,dword ptr [this] 00416E4B call dword ptr [edx] 00416E4D cmp esi,esp 00416E4F call @ILT+2795(__RTC_CheckEsp) (415AF0h) 00416E54 mov ecx,dword ptr [this] 00416E57 call A::g (4157FDh)
------解决方案--------------------
我说说我的一点理解啊。
当这句 p->h(),派生类指针调用基类函数。此时要进行一个this指针的转换。
p->h()相当于h(this)
此时this是B*;但是h()是A的函数,因此要进行一个指针的转换为this(A*);
转换后h()内部调用调用虚函数f(),即this->f(),因此实现了多态。
其中的指针转换与A *pa=new B一样
------解决方案--------------------