您的位置:首页 > 编程语言 > C语言/C++

C++中虚函数和非虚函数重载在继承时的区别

2016-03-01 17:48 288 查看
C++中虚函数和非虚函数重载在继承时的区别 - 每天进步一点点就好 - 博客频道 - CSDN.NET  http://blog.csdn.net/pendle/article/details/6574445

 这里唯一想说明的一点就是,使用虚函数继承时,当继承类被强转成基类后调用虚函数,调用的还是继承类的虚函数。而重载方式的继承类被强转成基类再调用重载函数,则调用的是基类的函数。废话不多说,上代码:

[cpp] view
plain copy

#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

 

通过汇编分析主要的代码片段如下:

 

[cpp] view
plain copy

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实例被强转后的函数表地址,函数定义如下:

[cpp] view
plain copy

_DWORD *__cdecl fun_GetAPFuns(_DWORD *p_fun_addr)  

{  

  _DWORD *result; // eax@1  

  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; // eax@1  

  result = p_fun_addr;  

  *p_fun_addr = &tag_A_Funs;  

  return result;  

}  

 

不难看出,针对((A*)&ap)->fun(); 这行代码调用,实际上是先获取了基类的函数表,然后又被继承类的函数表覆盖了。因此输出结果才会是AP:fun。

而对于直接重载继承的经过强转调用,在编译时就直接替换成基类的函数调用了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息