C++中虚函数工作原理和(虚)继承类的内存占用大小计算-1
上一篇 / 下一篇 2012-08-21 09:25:46 / 个人分类:C++
一、虚函数的工作原理51Testing软件测试网i.C.Iy0].KMk
51Testing软件测试网T,fI0x2}]0F d s每当创建一个包含有虚函数的类或从包含有虚函数的类派生一个类时,编译器就会为这个类创建一个虚函数表(VTABLE)保存该类所有虚函数的地址,其实 这个VTABLE的作用就是保存自己类中所有虚函数的地址,可以把VTABLE形象地看成一个函数指针数组,这个数组的每个元素存放的就是虚函数的地址。 在每个带有虚函数的类 中,编译器秘密地置入一指针,称为vpointer(缩写为VPTR),指向这个对象的VTABLE。 当构造该派生类对象时,其成员VPTR被初始化指向该派生类的VTABLE。所以可以认为VTABLE是该类的所有对象共有的,在定义该类时被初始化;而 VPTR则是每个类对象都有独立一份的,且在该类对象被构造时被初始化。
Abc8l"g4iwbZ:u09v B%d+O+U"J fm:R0 通过基类指针做虚函数调 用时(也就是做多态调用时),编译器静态地插入取得这个VPTR,并在VTABLE表中查找函数地址的代码,这样就能调用正确的函数使晚捆绑发生。为每个 类设置VTABLE、初始化VPTR、为虚函数调用插入代码,所有这些都是自动发生的,所以我们不必担心这些。51Testing软件测试网2w~Y;Ag AQ
2_,nk7X&^0#include<iostream> class A51Testing软件测试网%J8Np&~|8XkH 3mX*h/n
Z0class B : public A int main() c$v F ln0 system("pause"); |
毫无疑问,调用了B::fun1(),但是B::fun1()不是像普通函数那样直接找到函数地址而执行的。真正的执行方式是:首先取出pa指针所指向 的对象的vptr的值,这个值就是vtbl的地址,由于调用的函数B::fun1()是第一个虚函数,所以取出vtbl第一个表项里的值,这个值就是 B::fun1()的地址了,最后调用这个函数。因此只要vptr不同,指向的vtbl就不同,而不同的vtbl里装着对应类的虚函数地址,所以这样虚函 数就可以完成它的任务,多态就是这样实现的。51Testing软件测试网"sHP+T2e;l)y
51Testing软件测试网2clf)e,B"y而对于class A和class B来说,他们的vptr指针存放在何处?其实这个指针就放在他们各自的实例对象里。由于class A和class B都没有数据成员,所以他们的实例对象里就只有一个vptr指针。
+EvT:bJ F051Testing软件测试网}uN0f Gd^*s含有虚函数的对象在内存中的结构如下:
1\ieIuxjZm0class A I vOcV0Xh0{ ,NP0p'wgP-z0private:51Testing软件测试网OAH4y~7] int a;51Testing软件测试网5WL"kV-^(@Nt int b;51Testing软件测试网g-P%V@#_Z public: &f7w]c"|0 virtual void fun0() s\V}5Cf"c0 {51Testing软件测试网&}F1pZZU Ai cout<<"A::fun0"<<endl; ,ir sc d#P3SUD8N0 }51Testing软件测试网;^Up:oM)d%DE }; |
1、直接继承
J ki?*E1})K(V#U9T;m0那我们来看看编译器是怎么建立VPTR指向的这个虚函数表的,先看下面两个类:51Testing软件测试网 e/M0f:SiEC
51Testing软件测试网9qo E o1shJzO X$u
51Testing软件测试网xe!|#vbb class base51Testing软件测试网pA2?.uc class derived : public base51Testing软件测试网B3al-H T9hHL I^#w |