c++类内存布局的一些理解(1)
来源:互联网 发布:做平面图用什么软件 编辑:程序博客网 时间:2024/06/06 08:32
先看这段代码
//代码来自陈皓的博客http://blog.csdn.net/haoel/article/details/3081328class Base1 {public:int ibase1;Base1():ibase1(10) {}virtual void f() { cout << "Base1::f()" << endl; }virtual void g() { cout << "Base1::g()" << endl; }virtual void h() { cout << "Base1::h()" << endl; }};class Base2 {public:int ibase2;Base2():ibase2(20) {}virtual void f() { cout << "Base2::f()" << endl; }virtual void g() { cout << "Base2::g()" << endl; }virtual void h() { cout << "Base2::h()" << endl; }};class Base3 {public:int ibase3;Base3():ibase3(30) {}virtual void f() { cout << "Base3::f()" << endl; }virtual void g() { cout << "Base3::g()" << endl; }virtual void h() { cout << "Base3::h()" << endl; }};class Derive : public Base1, public Base2, public Base3 {public:int iderive;Derive():iderive(100) {}virtual void f() { cout << "Derive::f()" << endl; }virtual void g1() { cout << "Derive::g1()" << endl; }};
如果执行代码
Derive d;Base1* b1_ptr = &d;Base2* b2_ptr = &d;Base3* b3_ptr = &d;cout << b1_ptr << endl << b2_ptr << endl << b3_ptr << endl;
会得到结果
0012FF48
0012FF50
0012FF58
也就是说,虽然三个指针指向同一个对象,但是它们的值确实不同的!!!
这是因为,Base2的指针,不管指向Base2的对象还是子类Derive的对象,任何对这个指针的操作,都是按照Base2类的定义的内存布局来处理的。很明显,在一个Derive对象中Base2的内存布局在保存在Base1内存布局之后,并且有8字节的偏移(虚函数表和变量ibase1)。所以,编译做了一个隐式的转换(我恨这些编译器偷偷干的事),将各个指针指向它自己实际的内存布局。
为了符合这个要求,编译器在背后做了许多事情。例如上面这个例子,还有为什么dynamic_cast是必需的。下面解释dynamic_cast的原因:
对转换 Derive* d_ptr = dynamic_cast<Derive*>(b2_ptr) 来说,首先我们想象一下d_ptr的和b2_ptr的值应该是什么,b2_ptr的值已经有了,是0012FF50,而d_ptr的值则应该是0012FF48(因为Base1类的内存布局在Derive类的内存布局的顶端)。很明显,d_ptr和b2_ptr是有偏移量的,至于偏移量有多少,依赖于编译器的实现,只有编译器知道。因此Derive* d_ptr = b2_ptr是个严重的错误(虽然直观的讲b2_ptr确实指向一个Derive类实例)。
同样为了符合这个要求,虚函数的设计十分复杂。
个人认为,虚函数之所以这么设计的原因(这个得看陈皓的博客),就是要满足任意一个指针,不管指向什么,都要按照由它类定义所定义的内存布局来解释内存,从这个角度理解虚函数问题应该有点新意,有空再写
- c++类内存布局的一些理解(1)
- C的内存布局
- 关于C程序运行时的内存 的一些理解
- 深入理解C程序内存布局
- 深入理解C程序内存布局
- 深入理解C程序内存布局
- 关于C语言变量内存分配一些自己的理解。
- C语言程序的内存布局(1)
- 虚表的内存布局(c++)
- 关于内存的一些理解
- 关于内存的一些理解
- 关于内存的一些理解
- c/c++的内存布局
- C程序的内存布局
- C/C++的内存布局
- C程序代码的内存布局
- C/C++的内存布局
- C语言的内存布局
- java web开发学习-19 JNDI接口简介
- PHP再学习2——RT Thread + LwIP提交表单
- 题目1038:Sum of Factorials
- 菜单MENU学习日记
- java generic 介绍
- c++类内存布局的一些理解(1)
- hust 1017 dancing links
- 第十七周项目2-用指针玩字符串(统计单词个数)
- 17周项目五(6)。谁是小偷
- jQuery中的CSS操作
- sequence使用
- Postal Vans
- ffmpeg解码流程
- Effectvie C++ note2