C++对象模型之内存布局一
来源:互联网 发布:pokemon go unity源码 编辑:程序博客网 时间:2024/06/18 08:24
如果想学习在linux或者在linux平台下开发,学习C/或C++是非常好的选择.俗话说,术业有专攻,学一门技术,就尽量学得深,也可以作为行走江湖,混口饭吃的一项本领.
对于C,当初我是看了C与指针这门书,这本书讲解了很多我没有了解过的知识点,特别是指针讲解的很到位.最后还设计了C运行时内存模型.
对于C++的学习,我看了C++ Primer之后,进阶的书为深入理解C++对象模型,这本书讲解了C++类在内存中是如何布局以及成员函数是怎么调用,有助于理解C++多态是如何实现的.总之,受益匪浅.
接下来,我将用几篇博客聊聊C++对象模型.
无多态的对象布局
单个类
假设有以下一个类的定义:
123456789
class A{public:A(int a1=0,int a2=0);void A1();protected:int a1;int a2;};
如果类没有虚函数,那么class的布局和c语言的struct布局一样,只有成员变量.对象内存布局如图1所示.
继承类
有一个类B继承A,定义如下:
12345678
class B :public A{public:B(int a1=0,int a2=0,int b1=0);void B1();protected:int b1;};
子类的构造函数是先构造父类,在构造子类,所以类B对象内存布局只要在A成员之后加上B的成员即可,示意图如图1:
多态下对象内存布局
单个类
首先定义一个类,带有虚函数:
1234567891011
class A{public:A(int a1=0,int a2=0);virtual void A1();virtual void A2();virtual void A3();protected:int a1;int a2;};
因为class A带有虚函数,所以A对象的内存布局就要增加一个指针,指向类A的虚函数表.对象模型如图2所示.深入理解C++对象模型将指针放在了对象的末尾,但是现在主流的编译器都将指针放在了对象的首位置.
单继承
单继承类的定义如下:
12345678910
class B :public A{public:B(int a1=0,int a2=0,int b1=0);virtual void B1();virtual void A2();virtual void B2();protected:int b1;};
当父类有虚函数时,子类继承父类的虚函数表,而且虚函数的顺序是先父类的虚函数,再子类的虚函数;当父类的虚函数被子类重写时,则虚函数表中的父类虚函数指针要替换为子类的虚函数指针,示意图如图2.
实例验证
为了验证之前的对象模型是否正确,我写了如下程序进行验证:
1234567891011121314151617181920212223242526272829303132333435363738
using namespace std;class A{public:A(int a1=0,int a2=0){}virtual void A1(){cout<<"A::A1()"<<endl;}virtual void A2(){cout<<"A::A2()"<<endl;}virtual void A3(){cout<<"A::A3()"<<endl;}protected:int a1;int a2;};class B :public A{public:B(int a1=0,int a2=0,int b1=0){}virtual void B1(){cout<<"B::B1()"<<endl;}virtual void A2(){cout<<"A::A2()"<<endl;}virtual void B2(){cout<<"B::B2()"<<endl;}protected:int b1;};typedef void (*pfun)();//定义函数指针int main(void){B *bp=new B;pfun fun=NULL;//函数指针变量,用于循环迭代虚函数表for(int i=0;i<5;i++){fun=(pfun)*((long*)*(long*)bp+i);//因为我的ubuntu是64位的,所以用long类型.如果是32位的系统,可以用int类型.fun();}cout<<*((long*)*(long*)bp+5)<<endl;//输出虚函数表的结束符return 0;}
稍微解释下
1
fun=(pfun)*((long*)*(long*)bp+i)
- (long*)bp,将对象的指针类型转换为(long*)类型,用于取出虚函数表的地址.
- *(long*)bp,*为取出指针指向的值.此式子即虚函数表的地址,也就是第一个虚函数的地址.
- (long*)*(long*)bp,将虚函数表的地址指针转换为(long*),用于后续迭代.
- *(long*)*(long*)bp,*求指针值,即为第一个虚函数的地址,最后转换为pfun指针.
该程序输出结果为:
输出顺序和我上述一样.
多重继承,多继承以及菱形继承留在下一篇博客.
转载:http://write.blog.csdn.net/postedit
- C++对象模型之内存布局一
- C++对象模型之内存布局二
- C++对象模型之内存布局三
- C++对象模型之内存布局三(虚继承)
- JVM之内存中的对象模型
- Java锁(一)之内存模型
- 面向对象之内存分析(一)
- C语言之内存管理(一)
- C语言之内存对齐(一)
- Java之内存模型
- C++对象及多态实现探索之内存布局
- C++对象模型之内存区的使用
- C++对象模型之内存区的使用
- Java高级特性之内存模型(一)
- 二级指针作输入之内存模型一
- C之内存分类
- 操作系统实践之内存布局
- Java虚拟机之内存模型
- Java爬虫
- Android APP必备高级功能,消息推送之MQTT
- 验证码生成
- android 贪吃蛇简易实现
- HTTP 代理服务器技术选型之旅
- C++对象模型之内存布局一
- String、StringBuffer与StringBuilder之间区别
- webservice
- Linux进程入门学习(一)-认识进程
- 基于restful服务端接口(一)
- vue单页面之友盟代码统计
- Spring4 初级
- 从Android/Java基础之上学习C/C++语言(5)--C语言基础--结构体
- Mysql5.7版本(win7-64)安装方法