资源描述:
《C++虚函数机制分析》由会员上传分享,免费在线阅读,更多相关内容在工程资料-天天文库。
1、虚函数是面向对象编程语言里一个很重要的机制,下面我们以一个C++例了,分析其对应的C语言程序来说明虚函数的机制。面向对象有了一个垂要的概念就是对彖的实例,对彖的实例代表一个具体的对彖,故其肯定有一个数据结构保存这实例的数据,这一数据包括变量,接口函数指针,如果是虚函数,则有相应的虚函数指针,其他函数指针不包括。要讲虚函数机制,必须讲继承,因为只有继承才有虚函数的动态绑定功能,先讲下C++继承对彖实例内存分配基础知识:C++继承分为两种,普通继承和虚拟继承(virtual)0具体的继承乂根据父类中的两数是否virtual而不同。下面就单继承分为几种情况阐述:1.普通继
2、承+父类无virtual函数若子类没有新定义virtual函数此吋子类的布局是:由低地址->高地址为父类的元素(没有vptr),T类的元素(没有vptr).若子类有新定义virtual函数此时子类的布局是:由低地址-〉高地址为父类的元素(没有vptr),子类的元素(包含vptr,指向vtable.)2.普通继承+父类有virtual函数不管子类没有新定义virtiml函数此吋子类的布局是:由低地址-〉高地址为父类的元素(包含vptr),子类的元素.如果子类有新定义的virtual函数,那么在父类的vptr(也就是笫一个vptr)对应的vtable中添加一个函数指针.
3、3.v让tual继承若子类没有新定义virtual函数此时子类的布局是:由低地址-〉高地址子类的元素(有vptr),虚基类的元素.为什么这里会岀现vptr,因为虚基类派牛出來的类中,虚类的对象不在固定位置(猜测应该是在内存的尾部),需耍一个中介才能访问虚类的对彖.所以虽然没有virtual函数,了类也需要有一个vptr,对应的vtable屮需要有一项指向虚基类.若子类有新定义virtual两数此时子类的布局是与没有定义新virtual函数内存布局一致.但是在vtable中会多出新增的虚函数的指针.4.多重继承此时子类的布局是:由低地址-〉高地址为父类pl的元索Vpl
4、按照实际情况确定元索屮是否包含vptr),父类p2的元素(p2按照实际情况确定元素中是否包含vptr),子类的元素.如果所冇父类都没冇vptr,那么如果了类定义了新的virtualfunction,那么子类的元索中会有vptr,对应的viable会有相应的函数指针.如果有的父类存在vptr.如果了类定义了新的virtualfunction,会生成一个了类的vtable,这个了类的vtable是,在它的父类的vtable屮后添加这个新的虚函数指针生成的.因为子类分配的空间显示并没有新增加一•个4字节的指针空间,其实不管子类增加了多少新的虚函数,其空间大小不变,因为其和
5、虚函数相关的分配的空间就是一个vptr,是一个指针,也就是4字节,不变,要变是变在vtable.比如如下一个类:Classtestl(){};fun1(){};pubIicVirtuala(){println("testl:a”);};publicVirtualb(intb){println("testl:b”);};inta;}Classtest2extendstestl{fun2(){};publicVirtualb(intb){this->b++;println("test2:b”)};publieVitrualc(){pi'intln("test2:c}”)
6、}intb;}Intmain(){testla=newtest2();a.b();}首先我们看看下:类testl,test2实例大小及其内存分配图:testl的实例数据大小是:虚函数表指针(4)+iaptr接口指针+int变量大小(4)=12而test2的实例数据大小是:testl大小+其变屋b大小二12+4=16注意这是上面的提到的虚类继承,子类新增的虚函数不增加了类大小,只是在其虚函数表中体现。大家注意上面的testl,test2的构造函数,析构函数,funl,fun2都没加进去。下而看下实例数据内存分布图:下面看下其对应的c语言伪代码;1.已实现的函数:tes
7、tl.b(Sturcttestl*this,b){printin("testl”);};test2.b(Sturcttest2*this,b){println("test2:a”);test2.c(Sturcttest2*this){println("test2:b}”)}〃上面是虚函数实现testl.funl(Sturcttestl*this,){};test2.fun2(Sturcttest2*this){};//这个是普通函数,就是上面的,只不过变了名字而已。2.会生成类对应的结构体:structtestl{StuctTestlvtbl*vtbl;Tnta