您的位置:首页 > 其它

含有虚函数多重继承派生类内存布局

2016-03-15 23:01 302 查看
今天刚学关于c++多态,学了含有虚函数的类的内存情况。在多基类的派生类中,其中每个基类都含有虚函数,在这种情况下派生类的内存布局是怎么样的?

对于多重继承,有多少基类含有与派生类同名函数虚函数,派生类中就会存在多少个虚函数表和虚函数表指针,编译器会把第一个基类的虚函数表指针存放在派生类的起始地址,把第二个基类的虚函数表指针紧挨着第一个虚函数表指针存放,一次类推,直到存放完所有基类的虚函数表指针。

下面通过代码说明:

#include<iostream>

using namespace std;

typedef void (*Fun)(); //定义一个函数指针类型

class base

{

public:

virtual void fun()

{

cout<<"base fun"<<endl;

}

virtual char* fun2()

{

cout<<"base fun2"<<endl;

return NULL;

}

virtual ~base()

{

cout<<"base disconstructor"<<endl;

}

};

class base2

{

public:

virtual void fun()

{

cout<<"funbase2"<<endl;

}

virtual void funbase22()

{

cout<<"funbase22"<<endl;

}

};

class child :public base,public base2

{

public:

virtual void fun()

{

cout<<"fun child"<<endl;

}

};

int main(int argc, char const *argv[])

{

child b1;

int *p=NULL;

p=(int*)&b1;//将b1对象地址转换为int类型指针

//p是指向b1对象起始地址的,这个地址存放的是虚函数表地址

//(int*)把p转换成int类型指针

//((int *)p+0)是指向第0个基类的vfptr(虚函数表指针)存放地址

//同理((int *)p+1)是指向第1个基类的vfptr(虚函数表指针)存放地址

//*((int *)p+0)把地址中的值取出来,是个地址,但体现为整数。

//(int*)*((int *)p+0)把取出来的数值转换为一个地址(指针),此时的地址就是第0个虚函数表存放的地址

//同理(int*)*((int *)p+1)把取出来的数值转换为一个地址(指针)此时的地址就是第1个虚函数表存放的地址

//((int*)*((int *)p+0)+0)表示第0个虚函数表中第0个虚函数地址

//同理((int*)*((int *)p+0)+1)表示第0个虚函数表中第1个虚函数地址

//同理((int*)*((int *)p+1)+1)表示第1个虚函数表中第1个虚函数地址

//*((int*)*((int *)p+0)+0)就是把第0个虚函数表中第0个虚函数地址中的值取出来,这个数值是虚函数的地址

//(Fun)*((int*)*((int *)p+0)+0)就是把取出来的虚函数地址需要转换的指针转换成 void
(*Fun)()类型的函数指针,赋值给f指针

Fun f=(Fun)*((int*)*((int*)p+0)+0);//指向第0个虚函数

(*f)();//通过函数指针调用虚函数

f=(Fun)*((int*)*((int*)p+0)+1);//指向第1个虚函数

(*f)(); //通过函数指针调用虚函数

f=(Fun)*((int*)*((int*)p+0)+2);//指向第2个虚函数

(*f)(); //通过函数指针调用虚函数

//以上是输出第一个基类(也就是第0个基类的虚函数表中的虚函数)

f=(Fun)*((int*)*((int*)p+1)+0);//指向第0个虚函数

(*f)();//通过函数指针调用虚函数

f=(Fun)*((int*)*((int*)p+1)+1);//指向第1个虚函数

(*f)(); //通过函数指针调用虚函数

//以上是输出第二个基类(也就是第1个基类的虚函数表中的虚函数)

return 0;

}

输出结果是:

fun child

base fun2

base disconstructor

fun child

funbase22

此篇文章是本人参考书上和老师上课讲的知识总结出来的,如有错的地方,欢迎指出
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: