Chinaunix首页 | 论坛 | 博客
  • 博客访问: 187010
  • 博文数量: 50
  • 博客积分: 1053
  • 博客等级: 少尉
  • 技术积分: 577
  • 用 户 组: 普通用户
  • 注册时间: 2009-12-05 22:55
文章分类

全部博文(50)

文章存档

2016年(2)

2015年(1)

2014年(6)

2012年(11)

2011年(22)

2010年(5)

2009年(3)

我的朋友

分类: C/C++

2012-06-18 19:38:52

我理解的虚函数

原文地址:http://blog.chinaunix.net/uid-10780339-id-3247347.html



先列出问题。
1. c++中的关键词角度

Virtual 函数,纯虚函数,虚继承 。

2. 面向c++对象模型角度 看待虚函数

3. 虚函数的使用角度
        结合ctor ,dtor等等

4. 高级主题,简要说明虚函数的优点、缺点

5.高级主题,请举例说明虚函数性能低的情形,并给出解决方案。



这里,我的回答是:

1. c++中的关键词角度

Virtual 函数(多态的基础),纯虚函数(对应类为抽象类),虚继承 (使用于多重继承对应父类为虚基类)。


2. 面向c++对象模型角度 看待虚函数
首先要懂虚表,(基础是分开一般函数(没有使用virtual关键词修饰的)的布局,还有知道dtor位于虚表)
在不同的继承层次(线性,扇形,钻石型)知道,虚表的布局。
还有使用了多态的函数如何转换成 c语言 (我理解:先找到虚表,然后找到对应函数指针)


3. 虚函数的使用角度
ctor为什么不能够调用虚函数(我理解:所有的子类成员还没有初始化,此时访问时机不对。)
dtor为什么要设置为虚函数(调用子类dtor一次,就逐层销毁了所有(父类的,子类的)资源 )


4. 高级主题,简要说明虚函数的优点、缺点(答案详细参考引用文档1,2)
优点:我理解,就是多态
缺点:这里多说点
a.
比起编译时就确定地址的同类功能的函数调用, 动态连编时有效率损失.
b.
从指令级别讲,
     (1.虚函数的不确定性,会让编译器的 指令预测(或者说流水线技术)失效(详细参考)
     (2. 多了几条汇编指令(运行时得到对应类的函数的地址)
     (3. 编译器不能内联优化(仅在用父类引用或者指针调用时,不能内联)

        
        
5. 高级主题,请举例说明虚函数性能低的情形,并给出解决方案。(答案详细参考引用文档1,3)
        
当虚函数位于多层循环嵌套的核心部分时,这种情况更严重。还有另外一种性能下降显著的情况:当一系列虚函数频繁被调用时,我们不得不支付程序多次穿过“虚边界”的消耗。
                
解决方法很简单:把抽象提高到更高层即可。总的思路是不要让程序频繁在“虚-虚”或者“虚-非虚”之间切换。抽象提高后,把一系列虚函数或者循环中的虚函数都转移到更高一层,大大减低了切换的次数。
        
        
更多的关于虚函数的效率
详细点,效率有损失,数量级到底有多少,曾经有网友测试,1亿次系统调用会损失约1s,我个人觉得有点微不足道哈。但是这个测试案例不一定有代表性。

a.
虚函数调用效率和继承层数无关;
b.
其实虚函数还是挺快的。虚函数的效率到底低不低和实际要调用的函数的耗时有关,当函数本身的的耗时越长,则虚函数的影响则越小。
c.
如果真的要完全移除虚函数,那么如果要实现运行时多态,则要用到函数指针,据上面的分析,函数指针基本具有虚函数的所有缼点(要传递函数指针,同样无法内联,同样影响流水线),且函数指针会使代码混乱。

补充: 
幻の上帝 网友 提出使用 CRTP模式 解决效率问题
shanehan 网友提出 使用 boost::bind boost::function来替代虚函数


参考文档:
        1. c++ 虚函数机制效率问题(关于流水线)
         <http://blog.csdn.net/metalkittie/article/details/3281916> 
        2. C++中虚函数(virtual function)到底有多慢
         <http://blog.csdn.net/hengyunabc/article/details/7461919> 
        3. 【C++】虚函数的性能和vtable的细节——《C++游戏编程》读书笔记1
         < ... 2a7f15b21bba55.html> 
        4.[C++虚函数系列1]如何使用CRTP模式解决虚函数的效率损失问题? (
        http://blog.chinaunix.net/uid-9605822-id-2000053.html
阅读(1385) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~