CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
可用分押宝游戏火热进行中... 专题改版:Java Web 专题
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  C/C++ >  C++ 语言

多继承+虚继承时内存布局,sizeof()怎么计算?

楼主songxin328(masm)2006-09-24 11:25:20 在 C/C++ / C++ 语言 提问

今天看到<<C++编程思想>>多重继承一章,P366  
  按照作者的分析所述,我勉强推出了sizeof(Bottom)=36是怎么来的。  
  代码见下:(有省略)  
  然而我在运行它的时候,无论是vc6还是dev   c++显示的大小只有28B  
  这下我就完全弄不懂了,特此向各位牛人请教!  
   
  另:按照《虚继承之单继承的内存布局   》一文的分析,就应该是36啊,这倒底是  
  怎么回事呢?(该文出处:   http://rkfang.cnblogs.com/archive/2004/10/10/50599.aspx   )  
   
  =================  
  #include<iostream>  
  #include<cstdlib>  
    using   namespace   std;  
    class   Top  
    {  
      protected:  
              int   x;  
      public:  
              Top(int   n):x(n){cout<<"Top"<<endl;}  
              virtual   ~Top(){}  
         
    };  
    class   Left:virtual   public   Top  
    {  
      protected:  
              int   y;  
      public:  
              Left(int   m,int   n):Top(m){y=n;cout<<"Left"<<endl;}  
    };  
    class   Right:public   virtual   Top  
    {  
        protected:  
                int   z;  
        public:  
                Right(int   m,int   n):Top(m){z=n;cout<<"Right"<<endl;}      
    };  
    class   Bottom:public   Left,public   Right  
    {  
        int   w;  
        public:  
                Bottom(int   i,int   j,int   k,int   m):Top(i),Left(i,j),Right(i,k),w(m)          
              {  
                cout<<"Bottom"<<endl;  
                }          
    };  
    int   main()  
    {  
          Bottom   b(1,2,3,4);  
          cout<<"sizeof(b)   "<<sizeof(b)<<","<<sizeof(Bottom)<<endl;  
          cout<<sizeof(Left)<<","<<sizeof(Right)<<","<<sizeof(Top)<<endl;  
          for(int   i=0;i<sizeof(b);i+=4)  
                  cout<<*(reinterpret_cast<int*>((&b)+i))<<"________"<<endl;  
          system("PAUSE");          
    }  
  ================= 问题点数:100、回复次数:20Top

1 楼langzi8818(┤天道酬勤┝爱老婆┦┷我是来学习滴┷)回复于 2006-09-24 11:36:14 得分 5

接分,每个编译器实现不同Top

2 楼wanfustudio(雁南飞:知识之败,慕虚名而不务潜修也)回复于 2006-09-24 12:16:35 得分 5

不晓得   !  
   
  顶上去!Top

3 楼chenhu_doc(^0^纯一狼^0^ 看书看到大笑,直到不能自已)回复于 2006-09-24 12:31:45 得分 10

看inside   the   cpp   object   model  
   
    主要是  
    对象的vptr指针占用  
    和字节对齐的需要  
    两种情况占用内存。Top

4 楼chenhu_doc(^0^纯一狼^0^ 看书看到大笑,直到不能自已)回复于 2006-09-24 12:43:19 得分 0

当然,vptr占用考虑要单纯些,  
  字节对齐看个例子就可以了。  
   
  参考inside   the   cpp   object   model  
  的     3.4   Inheritance   and   the   Data   Member    
   
   
  Top

5 楼OOPhaisky(异化$渴望成功~~)回复于 2006-09-24 12:50:47 得分 50

按照一般情况,36应该是正确的,计算方法如下:  
  virtual   class   Top子对象(1个):4+4=8bytes(int   x:4bytes,   vptr:4bytes)  
  class   Left子对象(1个):4+4+4=12bytes(int   y:4bytes,   vptr:4bytes,pointer   to   virtual   base   class:4bytes)  
  class   Right子对象(1个):4+4+4=12bytes(int   z:4bytes,   vptr:4bytes,pointer   to   virtual   base   class:4bytes)  
  class   Bottom子对象(1个):4bytes(int   w:4bytes)  
  所以一共8+12+12+4=36bytes。  
   
  但是,各家编译器厂商的实现方法各有不同,比如,如果将class   Left子对象和class   Right子对象中的pointer   to   virtual   base   class与vptr合并到一起,那么class   Left子对象和class   Right子对象的大小就都是8bytes了,这样一来总共的大小就变成28bytes了。Top

6 楼songxin328(masm)回复于 2006-09-24 13:28:43 得分 0

谢谢各位的解答  
  在dev   c++中各个类大小分别是  
  Bottom   28  
  Left       16(也许这个时候相当于Left是Top的最终实现,所以Top的数据成员还是有的)  
  Right     16  
  Top         8  
  我是这样计算的:  
  Bottom:   vptr_Bottom   +   (int   w)   +   vptr_Left   +   vbtbl_Left   +   vptr_Right  
                  +   vbtbl_Right   +   (int   y)   +   (int   z)   +   (int   x)   +   vptr_Top   =   40(忘了最开始怎么推出的36了:()  
  OOPhaisky(异化$渴望成功~~)   在计算Bottom时为什么不考虑Bottom的虚函数指针呢?如果vptr_Bottom没有的话那么我的答案也是36了:)  
  另外,上面的字节数(28,16,16,8)无论是VC6   or   Dev   c++都是一样的  
  这里的数据int和指针都是4B,我想暂时没有因对齐而加入的字节吧?  
   
  1.   麻烦大家看看我的推导哪儿错了(都=40了)?  
  2.   28,36,怎么算出来的?  
  再次orz   谢!Top

7 楼steedhorse(晨星)回复于 2006-09-24 13:43:37 得分 20

忘了最开始怎么推出的36了:(  
  =============================  
  vptr_Bottom和vptr_Left(或vptr_Right,总归两者之一)可以共享。Top

8 楼steedhorse(晨星)回复于 2006-09-24 13:49:18 得分 0

还有的编译器实现中会把指向虚基类子对象的那个指针同样给塞到虚函数表的某一项中去,所以可能连36都不用了。  
  知道各种编译器各不相同就可以了。:)  
  究竟怎么个“不同”法,唉,什么实现都可能有。:(别去多管了。Top

9 楼songxin328(masm)回复于 2006-09-24 14:24:03 得分 0

感谢晨星的解答^_^  
  同样谢谢楼上的各位  
  今天晚点时候结贴:)Top

10 楼sinall()回复于 2006-09-24 15:31:03 得分 5

Top:   4(vptr)   +   4(x)   =   8  
  Left:   4(vptr)   +   4(vptr   to   Top)   +   4(x)   +   4(y)   =   16  
  Right:   4(vptr)   +   4(vptr   to   Top)   +   4(x)   +   4(z)   =   16  
  Bottom:   4(vptr)   +   4(vptr   to   Left)   +   4(vptr   to   Right)   +   4(x)   +   4(y)   +   4(z)   +   4(w)   =   28  
  个人猜想,欢迎指正。Top

11 楼songxin328(masm)回复于 2006-09-24 15:44:34 得分 0

to   sinall:  
          你所说的vptr   to   Top   是不是就是指向虚基表的指针?vbtbl_ptr_Top??  
  另外,因为Bottom的size只有28,除去四个数据成员16B后,只能存放3个指针    
  这三个放的是啥东东呢?  
  如sinall所言的:4(vptr)   +   4(vptr   to   Left)   +   4(vptr   to   Right)    
  还是:vptr_bottom,Left及Right中的vptr   (或   vbtbl_ptr)?Top

12 楼corrupt(喜欢 睡在床板下 的思考)回复于 2006-09-24 15:49:10 得分 5

inside   object   model...  
  说的自己也不懂了Top

13 楼OOPhaisky(异化$渴望成功~~)回复于 2006-09-24 18:02:58 得分 0

OOPhaisky(异化$渴望成功~~)   在计算Bottom时为什么不考虑Bottom的虚函数指针呢?如果vptr_Bottom没有的话那么我的答案也是36了:)  
  ---------------------------------------------------------------------------------  
  楼主可以为Bottom加上一个vptr指针,符合标准,行为也正确,但是我要说这是完全没有必要的!因为Bottom可以和Left或者Right共享vptr指针,因为Bottom对象一定是一个Left或者Right对象,其中一定有Left或者Right的成分,所以只要Left或者Right有vptr,那么Bottom就一定有vptr了。因此,相信大部分编译器都不会为Bottom单独设置一个vptr。  
  楼主如果对这一点有疑问,可以看看《more   effective   c++》120页,就是说的这个问题(inside   the   cpp   model中应该也有介绍,但是太杂了,没找到)。Top

14 楼OOPhaisky(异化$渴望成功~~)回复于 2006-09-24 18:41:28 得分 0

我将<<more   effective   c++>>中的话给楼主贴一下吧:  
  -----------------------------------------------------------------------------------  
  class   A   {...};  
  class   B   :virtual   public   A   {...};  
  class   C   :virtual   public   A   {...};  
  class   D   :public   B,   public   C   {...};  
   
  ......  
   
  ...虽然涉及四个classes,却只出现三个vptrs。如果编译器喜欢,当然可以产生四个vptrs,但是三个已经足够了(B和D可以共享同一个vptr)。大部分编译器会采用这项好处,降低编译器所带来的额外开销。  
  -----------------------------------------------------------------------------------Top

15 楼songxin328(masm)回复于 2006-09-24 21:45:59 得分 0

太感谢   OOPhaisky(异化$渴望成功~~)     了!  
  我把整个大家的回帖又看了一遍,现在差不多理解了,虽然不  
  算太清楚:)  
  现在结贴。  
  3x   2   all!Top

16 楼guqst(过关斩将)回复于 2006-09-26 09:13:17 得分 0

bottom:  
  2个vbtable  
  1个vftable  
  4个成员Top

17 楼michaelysj(其实我很傻...)回复于 2006-10-28 21:22:40 得分 0

markTop

18 楼jiang_nan1981()回复于 2006-10-29 20:02:08 得分 0

markTop

19 楼zjbirdman()回复于 2006-11-12 20:01:02 得分 0

markTop

20 楼dukang_2005(杜康)回复于 2007-04-16 10:11:19 得分 0

你要是在Left,和Right中都加一个虚函数(析构除外)的话就36了Top

相关问题

关键词

得分解答快速导航

  • 帖主:songxin328
  • langzi8818
  • wanfustudio
  • chenhu_doc
  • OOPhaisky
  • steedhorse
  • sinall
  • corrupt

相关链接

  • C/C++ Blog
  • C/C++类图书
  • C/C++类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
世纪乐知(北京)网络技术有限公司 版权所有, 京 ICP 证 020026 号
北京创新乐知广告有限公司 提供技术支持
Copyright © 2000-2007, CSDN.NET, All Rights Reserved
GongshangLogo