ViCross

C++编译期系列<虚函数>

类的虚函数:

 很多人都知道虚函数表, 对于虚函数, 各种论坛上充斥着很多的批评:
 1. 让程序流程变得复杂;
 2. 带来的虚表, 在空间和时间上都有消耗;
 甚至有些"Niu的人"认为, 要用C完全替代C++;
 
 先查看虚函数的实现原理: 虚函数表和函数替换; 
 >>空间:
 1. 每个类有一个虚表(简单的认为, 它像一个类的静态成员变量),
 2. 每个对象有一个保留该表的指针;
 所以主要内存消耗应该在"2"上面. 使用的时候要注意, 如果是很简单的数据结构, 少4个和8个字节是有意义的;
 如果是大类, 这个消耗是极其微小的;
 编译期间, 生成一个虚表, 并替换所有通过指针访问的虚函数(替换成虚表[idx]),  构造对象期间, 绑定虚表指针.
 
 >>执行:
 通过指针调用的虚函数, 在编译期间会被编译器默认的替代为: "虚表[idx]";
 "虚表[idx]":
 1. 它没有表索引带来的性能损耗;
 2. 执行的时候, 只是一次数组的定位访问, 然后进入函数入口;
 所以, 虚函数的额外时间使用代价, 应该跟一个"条件判断"等价, 不会有特别大的损耗;
 
 但是虚表带来的多态是支持面向对象语言的最大特点;
 在C++以后, C#, Java都相继扩展了虚表的使用范围,
 显然, 这些语言背后的智囊都是绝顶高手, 他们在权衡了多态的利与弊之后, 还是作出了"扩展虚表"的决定.
 
 上面提到的虚函数调用一直是"通过指针"的, 如果通过对象会怎么样呢?
 编译器会把对象直接调用的虚函数直接当非虚函数来直接替换成函数入口, 而不通过虚表, 这是高效,
 它的背后也说明了一点: 只有指针才能实现多态.

posted on 2008-09-28 23:49  ViCross  阅读(397)  评论(0编辑  收藏  举报

导航