关于程序设计语言本身的设计有许多有趣的话题,比如,为何C++中的类成员函数没有采用类似Java中的“全虚”设计?
1) 从语言本身设计上看,
效率定然是c++当初设计时考虑的重点之一,举个例子,为了节省不必要的VTable开销,ATL用template技术静态转换来模拟动态绑定以支持COM特性的实现;和C的兼容,就VTable角度看,问题不大,因为后者可以用函数指针数组来模拟;
2) 再从大多数应用中常见的类继承体系上看,
除了整个继承体系所统一开放出来的接口集(也就是由虚函数所组成),在继承体系的每个层面另外会有大量的其他辅助成员函数(其数量通常比虚函数多的多),这些成员函数完全没必要设计成虚函数;
3) 从其他语言看,
即使较新的虚拟机语言C#(Java算是较老的虚拟机语言),反而定义了比C++更为严格更为显式的成员方法实现或覆盖或重载或新建的规则;这是非常重要的对C++以及Java设计思想的反思。
4) 从语言的适用场合看,
我们现在的讨论,绝大多数情况下带有一个非常重要的默认前提,那就是在用户态模式下使用C++,如果放宽这个约束,在内核模式下使用C++,那情况又完全不同了。
引用下面这个文档的观点,http://www.microsoft.com/china/whdc/driver/kernel/KMcode.mspx
首先,用户态下非常廉价几乎不用考虑的资源,在内核中是非常昂贵的,比如内核堆栈一般就3个page;
在内核不能分页(paging)时必须保证将被执行的所有代码和数据必须有效的驻留在物理内存中,如果这时需要多驻留几张虚表以及虚表指针那还是显得非常昂贵的,同时编译器为虚函数,模板等生成代码的方式,让开发人员很难确定要执行一个函数所需要的所有代码的所在位置,因此也无法直接控制用于安置这些代码的节(个人认为可能通过progma segment/datasegment/codesegment对于代码和数据进行集中控制),因此在需要这些代码时,可能已经被page out了;
所有涉及类层次结构,模板,异常等等这样的一些语言结构在内核态中都可能是不安全的,最好是把类的使用限定为POD类,回到我们的主题虚函数,也就是说内核态下类设计中没有虚函数。