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。
而对于直接重载继承的经过强转调用,在编译时就直接替换成基类的函数调用了。
这里唯一想说明的一点就是,使用虚函数继承时,当继承类被强转成基类后调用虚函数,调用的还是继承类的虚函数。而重载方式的继承类被强转成基类再调用重载函数,则调用的是基类的函数。废话不多说,上代码:
[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。
而对于直接重载继承的经过强转调用,在编译时就直接替换成基类的函数调用了。
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- 关于指针的一些事情
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- c#中虚函数的相关使用方法
- PostgreSQL教程(三):表的继承和分区表详解
- Lua中调用C++函数示例
- Lua面向对象之类和继承浅析
- Lua教程(一):在C++中嵌入Lua脚本
- 浅析Ruby中继承和消息的相关知识
- Lua教程(二):C++和Lua相互传递数据示例
- 设计引导--一个鸭子游戏引发的设计理念(多态,继承,抽象,接口,策略者模式)
- C++联合体转换成C#结构的实现方法
- C++高级程序员成长之路
- C++编写简单的打靶游戏
- C++ 自定义控件的移植问题
- C++变位词问题分析
- C/C++数据对齐详细解析
- C++基于栈实现铁轨问题
- C++中引用的使用总结