好吧,我承认标题是用来搞笑的,因为内容实在谈不上有什么深度,只是介绍下内存布局,深度不够只好浅度来凑:-)
单刀直入,这次博客计划讨论如下三种情形下的C++对象内存布局:
1.单继承带覆盖;
2.带重复继承的多重继承带覆盖;
3.带重复继承的多重虚拟继承带覆盖
之所以只给出这三种情况是因为个人认为其余的情形是平凡的,被以上三种所蕴含;其次这几种情况都是包含成员变量的,这也是和上篇博客的区别所在;最后就是这篇决定调整一下叙述方式:先给出预期结果,然后通过运行结果来验证我们的想法。
以下程序运行环境均是32位WIN7系统 + Visual Studio 2010。
一、单继承带覆盖:
先上代码:
1 #include <iostream> 2 using namespace std; 3 4 //单继承带覆盖有数据成员和成员函数的情况下内存布局 5 class Base{ 6 7 public: 8 Base():_base(10){} 9 virtual void f(){ cout<<"Base::f()"<<endl; } 10 private: 11 int _base; 12 }; 13 14 class Derive: public Base{ 15 16 public: 17 Derive():_derive(100){} 18 virtual void f(){ cout<<"Derive::f()"<<endl;} 19 virtual void g(){ cout<<"Derive::g()"<<endl;} 20 private: 21 int _derive; 22 }; 23 24 class DDerive: public Derive{ 25 26 public: 27 DDerive():_dderive(1000){} 28 virtual void f(){ cout<<"DDerive::f()"<<endl;} 29 virtual void g(){ cout<<"DDerive::g()"<<endl;} 30 virtual void h(){ cout<<"DDerive::h()"<<endl;} 31 private: 32 int _dderive; 33 }; 34 35 int main(){ 36 37 DDerive d; 38 typedef void (*Fun)(); 39 Fun pFun = NULL; 40 //首先通过函数指针调用成员函数 41 pFun = (Fun)*((int*)*((int*)(&d) + 0) + 0); 42 pFun(); 43 pFun = (Fun)*((int*)*((int*)(&d) + 0) + 1); 44 pFun(); 45 pFun = (Fun)*((int*)*((int*)(&d) + 0) + 2); 46 pFun(); 47 //再通过函数指针访问派生类中的数据成员: 48 cout<<"Base::_base = " <<*(int*)((int*)(&d) + 1)<<endl; 49 cout<<"Derive::_derive = " <<*(int*)((int*)(&d) + 2)<<endl; 50 cout<<"DDerive::_dderive = "<<*(int*)((int*)(&d) + 3)<<endl; 51 52 getchar(); 53 return 0; 54 }
预期内存布局图示如下:
运行结果为:
可以看到,运行结果和预期完全一致。
二、带重复继承的多重继承带覆盖:
三、带重复继承的多重虚拟继承带覆盖:
时间: 2024-11-05 17:27:54