1.C++函数调用的实现
将虚函数、多重继承、虚继承加入考虑后,C++的函数调用变得很复杂,其实取到这个函数地址还是很简单的,无非就是某个地方存着一个函数表,然后对象中的某个地方存着这个表的地址,通过一步间接地址计算就可以找到这个函数地址了。难得是,在多重继承和虚继承的情况下,调用函数时,是要偏移this指针的,例如以第二继承链上的类的指针,调用虚函数,而该虚函数又在最后的派生类中被重载,那么就需要把该指针从指向代表第二继承链的内存部分偏移到指向这个对象的首地址,这个偏移值是多少呢,不同的继承体现就是不同的,如果把虚继承考虑进去就更麻烦了,对于这个复杂的问题,不同的编译器厂商有不同的策略,我也记不住那么多,所以就记住这个要偏移就可以了。
之前我说的,“多继承统统按照C#那样一个基类,配n个接口,即使那n个接口有一些是继承自同一个接口的,也不应该用虚继承”,这是错的,CEGUI用虚继承是对的。
对于菱形继承
A
/ \
B C
\ /
D
如果不用虚继承,那么D*无法转化为A*,因为D的对象里面有两份A的数据,即使这数据只是一个vptr。如果程序里面完全不需要把D*转为A*那么不用虚继承也没问题,但如果不转,说明也没有必要有A这一层了,所以这种情况,虚继承时必须的,无论A里面是否有数据成员,都是必须的。
2.什么时候必须在ctor和dtor中实例化vptr
下面这段是我2012.11.19写的,其中有错误
2.关于虚函数表指针设置的时机
在一般情况下,每个类在构造和析构的时候,在运行函数体之前都需要首先将自己的vptr指向为当前ctor或者dtor所在的类的那个vtbl。如果ctor和dtor里面没有运行虚函数,这样的设置显然造成了效率的浪费,我估计这里应该有优化的,即哪一层ctor或者dtor调了虚函数,则那一层的ctor和dtor里面设置vptr,另外能够实例化的那一层类的ctor也必须设置vptr,否则实例化出来的对象的vptr就不对了,从而虚函数机制也就会出错。
ctor和dtor中调用虚函数是不走虚函数机制的,直接静态决议为当前类的所有的那个虚函数,从这个角度说,如果这个类不能被实例化,那么它就不需要设置vptr,但被静态决议调用后的那个虚函数里面是可能调用虚函数的,而这种调用必须走虚函数机制,所以需要设置vptr,编译器的优化是,如果该类是纯虚类,且ctor或dtor中没有调用类函数,则可以不设置vptr,否则必须设置,当然也可以再优化一点,查调用的函数里面有没有调用虚函数,一直查下去~~~确定确实没有走虚函数机制,那么也可以不设。