这里唯一想说明的一点就是,使用虚函数继承时,当继承类被强转成基类后调用虚函数,调用的还是继承类的虚函数。而重载方式的继承类被强转成基类再调用重载函数,则调用的是基类的函数。废话不多说,上代码:
#include <iostream> using namespace std; class A { public : virtual void fun() { cout << "A::fun" << endl; } }; class AP : A { public : virtual void fun() { cout << "AP:fun" << endl; } }; class B { public : void fun() { cout << "B:fun" << endl; } }; class BP : B { public : void fun() { cout << "BP:fun" << endl; } }; int main( int argc, char * argv[]) { A a; a.fun(); AP ap; ((A*)&ap)->fun(); B b; b.fun(); BP bp; ((B*)&bp)->fun(); return 0; }
这段代码执行的输出是:
A::fun AP:fun B:fun B:fun
通过汇编分析主要的代码片段如下:
fun_A__fun(); fun_GetAPFuns(&p_fun_addr); (*(void (__cdecl **)( int *))p_fun_addr)(&p_fun_addr); fun_B__fun(); fun_B__fun();
其中fun_GetAPFuns函数,就是获取AP实例被强转后的函数表地址,函数定义如下:
_DWORD *__cdecl fun_GetAPFuns(_DWORD *p_fun_addr) { _DWORD *result; fun_GetAFuns(p_fun_addr); result = p_fun_addr; *p_fun_addr = &tag_AP_Funs; return result; } _DWORD *__cdecl fun_GetAFuns(_DWORD *p_fun_addr) { _DWORD *result; result = p_fun_addr; *p_fun_addr = &tag_A_Funs; return result; }
不难看出,针对((A*)&ap)->fun(); 这行代码调用,实际上是先获取了基类的函数表,然后又被继承类的函数表覆盖了。因此输出结果才会是AP:fun。
而对于直接重载继承的经过强转调用,在编译时就直接替换成基类的函数调用了。
FROM: http://blog.csdn.net/pendle/article/details/6574445