#include <iostream>
#include <stdio.h>
using namespace std;
class X{};
class Y: public virtual X{};
class Z: public virtual X{};
class A: public Y, public Z{};
int main()
{
printf("Y:%d Z:%d A:%d\n", sizeof(Y), sizeof(Z), sizeof(A));
return 0;
}
运行平台:linux gcc4.6
结果:Y:8 Z:8 A:16
请问A为什么不是12?
按照对象模型中理论,A继承于X,X不论被继承多少层,都只有一个suboject 实体,不应该A大小为9吗,然后内存对其,最终sizeof为12吗?哪位解释下,为什么结果是16?
13 个解决方案
#1
这不是C++标准的东西吧, 这依赖于编译器自身
#2
楼主知道不知道有个东西叫virtual table
#3
恩,这要看自身编译器的实现!!好像论坛蛮多这样子的讨论贴
#4
诶 是空的class啊 楼主可以debug看一看A里面到底有什么 我也忘了。。。
#5
不知道的话,我能够知道标准上:应该是9吗?
#6
标准上应该12,但是g++显示的好像不是12,而是16,所以,不明白g++对象模型是怎么样的呀?所以想请教下的呀!
#7
研究包含虚基类的对象的大小 没有太大意义,因为不同编译器的实现差异太大。
#8
lz这个明显是inside the c++ object model上面的例子,
书上说的很明确了 视编译器而定
书上说的很明确了 视编译器而定
#9
参考一下
c:\demo>type demo.cpp
#include <stdio.h>
using namespace std;
class X{};
class Y: public virtual X{};
class Z: public virtual X{};
class FooBar: public Y, public Z{};
int main()
{
printf("Y:%d Z:%d A:%d\n", sizeof(Y), sizeof(Z), sizeof(FooBar));
return 0;
}
c:\demo>cl /nologo /W4 /EHsc /d1reportSingleClassLayoutFooBar demo.cpp
demo.cpp
class FooBar size(8):
+---
| +--- (base class Y)
0 | | {vbptr}
| +---
| +--- (base class Z)
4 | | {vbptr}
| +---
+---
+--- (virtual base X)
+---
FooBar::$vbtable@Y@:
0 | 0
1 | 8 (FooBard(Y+0)X)
FooBar::$vbtable@Z@:
0 | 0
1 | 4 (FooBard(Z+0)X)
vbi: class offset o.vbptr o.vbte fVtorDisp
X 8 0 4 0
c:\demo>demo
Y:4 Z:4 A:8
c:\demo>
#10
参考一下
c:\demo>type demo.cpp
#include <stdio.h>
using namespace std;
class X{};
class Y: public virtual X{};
class Z: public virtual X{};
class FooBar: public Y, public Z{};
int main()
{
printf("Y:%d Z:%d A:%d\n", sizeof(Y), sizeof(Z), sizeof(FooBar));
return 0;
}
c:\demo>cl /nologo /W4 /EHsc /d1reportSingleClassLayoutFooBar demo.cpp
demo.cpp
class FooBar size(8):
+---
| +--- (base class Y)
0 | | {vbptr}
| +---
| +--- (base class Z)
4 | | {vbptr}
| +---
+---
+--- (virtual base X)
+---
FooBar::$vbtable@Y@:
0 | 0
1 | 8 (FooBard(Y+0)X)
FooBar::$vbtable@Z@:
0 | 0
1 | 4 (FooBard(Z+0)X)
vbi: class offset o.vbptr o.vbte fVtorDisp
X 8 0 4 0
c:\demo>demo
Y:4 Z:4 A:8
c:\demo>
vc 2010
#11
#include <iostream>
#include <stdio.h>
using namespace std;
class X{};
class Y: public virtual X{};
class Z: public virtual X{};
class A: public Y, public Z{};
int main()
{
printf("Y:%d Z:%d A:%d\n", sizeof(Y), sizeof(Z), sizeof(A));
return 0;
}
运行平台:linux gcc4.6
结果:Y:8 Z:8 A:16
请问A为什么不是12?
按照对象模型中理论,A继承于X,X不论被继承多少层,都只有一个suboject 实体,不应该A大小为9吗,然后内存对其,最终sizeof为12吗?哪位解释下,为什么结果是16?
这不是C++标准的东西吧, 这依赖于编译器自身
标准上应该12,但是g++显示的好像不是12,而是16,所以,不明白g++对象模型是怎么样的呀?所以想请教下的呀!
标准从来没规定应该是多少。
你说的“g++对象模型”根本不是标准的内容,标准本身不是哪个具体的编译器厂商定的。
标准里有个关于大小的规定倒是,就是sizeof(X)不能为零,但是被另一个STD-LY类型(之前叫POD类型)继承S的时候,sizeof(S)可以只考虑S自身的成员占用情况(而让X在其中不占任何实际空间)
但是lz的例子里,Y、Z虚继承于X,结果Y、Z、A都已经不是STD-LY类型了,所以sizeof具体应该为多少,标准已经没有相应的规定了,只要是固定大小就行,编译器设计者可以自己决定
#12
补充一下,虚继承、虚函数的实现方式目前有虚表、二叉树、hash表等方式,现在主流的编译器多使用虚表这种实现方式、讨论的也比较多,但不要认为是标准规定了用虚表实现。虚表不是标准里的内容、标准也没规定该用什么方式实现虚函数、虚继承这些。
#13
哎,楼主《深度探索C++对象模型》基本白看了,竟然把virtual继承无视了。
#1
#include <iostream>
#include <stdio.h>
using namespace std;
class X{};
class Y: public virtual X{};
class Z: public virtual X{};
class A: public Y, public Z{};
int main()
{
printf("Y:%d Z:%d A:%d\n", sizeof(Y), sizeof(Z), sizeof(A));
return 0;
}
运行平台:linux gcc4.6
结果:Y:8 Z:8 A:16
请问A为什么不是12?
按照对象模型中理论,A继承于X,X不论被继承多少层,都只有一个suboject 实体,不应该A大小为9吗,然后内存对其,最终sizeof为12吗?哪位解释下,为什么结果是16?
这不是C++标准的东西吧, 这依赖于编译器自身
#2
楼主知道不知道有个东西叫virtual table
#3
恩,这要看自身编译器的实现!!好像论坛蛮多这样子的讨论贴
#4
楼主知道不知道有个东西叫virtual table
诶 是空的class啊 楼主可以debug看一看A里面到底有什么 我也忘了。。。
#5
楼主知道不知道有个东西叫virtual table
不知道的话,我能够知道标准上:应该是9吗?
#6
#include <iostream>
#include <stdio.h>
using namespace std;
class X{};
class Y: public virtual X{};
class Z: public virtual X{};
class A: public Y, public Z{};
int main()
{
printf("Y:%d Z:%d A:%d\n", sizeof(Y), sizeof(Z), sizeof(A));
return 0;
}
运行平台:linux gcc4.6
结果:Y:8 Z:8 A:16
请问A为什么不是12?
按照对象模型中理论,A继承于X,X不论被继承多少层,都只有一个suboject 实体,不应该A大小为9吗,然后内存对其,最终sizeof为12吗?哪位解释下,为什么结果是16?
这不是C++标准的东西吧, 这依赖于编译器自身
标准上应该12,但是g++显示的好像不是12,而是16,所以,不明白g++对象模型是怎么样的呀?所以想请教下的呀!
#7
研究包含虚基类的对象的大小 没有太大意义,因为不同编译器的实现差异太大。
#8
lz这个明显是inside the c++ object model上面的例子,
书上说的很明确了 视编译器而定
书上说的很明确了 视编译器而定
#9
参考一下
c:\demo>type demo.cpp
#include <stdio.h>
using namespace std;
class X{};
class Y: public virtual X{};
class Z: public virtual X{};
class FooBar: public Y, public Z{};
int main()
{
printf("Y:%d Z:%d A:%d\n", sizeof(Y), sizeof(Z), sizeof(FooBar));
return 0;
}
c:\demo>cl /nologo /W4 /EHsc /d1reportSingleClassLayoutFooBar demo.cpp
demo.cpp
class FooBar size(8):
+---
| +--- (base class Y)
0 | | {vbptr}
| +---
| +--- (base class Z)
4 | | {vbptr}
| +---
+---
+--- (virtual base X)
+---
FooBar::$vbtable@Y@:
0 | 0
1 | 8 (FooBard(Y+0)X)
FooBar::$vbtable@Z@:
0 | 0
1 | 4 (FooBard(Z+0)X)
vbi: class offset o.vbptr o.vbte fVtorDisp
X 8 0 4 0
c:\demo>demo
Y:4 Z:4 A:8
c:\demo>
#10
参考一下
c:\demo>type demo.cpp
#include <stdio.h>
using namespace std;
class X{};
class Y: public virtual X{};
class Z: public virtual X{};
class FooBar: public Y, public Z{};
int main()
{
printf("Y:%d Z:%d A:%d\n", sizeof(Y), sizeof(Z), sizeof(FooBar));
return 0;
}
c:\demo>cl /nologo /W4 /EHsc /d1reportSingleClassLayoutFooBar demo.cpp
demo.cpp
class FooBar size(8):
+---
| +--- (base class Y)
0 | | {vbptr}
| +---
| +--- (base class Z)
4 | | {vbptr}
| +---
+---
+--- (virtual base X)
+---
FooBar::$vbtable@Y@:
0 | 0
1 | 8 (FooBard(Y+0)X)
FooBar::$vbtable@Z@:
0 | 0
1 | 4 (FooBard(Z+0)X)
vbi: class offset o.vbptr o.vbte fVtorDisp
X 8 0 4 0
c:\demo>demo
Y:4 Z:4 A:8
c:\demo>
vc 2010
#11
#include <iostream>
#include <stdio.h>
using namespace std;
class X{};
class Y: public virtual X{};
class Z: public virtual X{};
class A: public Y, public Z{};
int main()
{
printf("Y:%d Z:%d A:%d\n", sizeof(Y), sizeof(Z), sizeof(A));
return 0;
}
运行平台:linux gcc4.6
结果:Y:8 Z:8 A:16
请问A为什么不是12?
按照对象模型中理论,A继承于X,X不论被继承多少层,都只有一个suboject 实体,不应该A大小为9吗,然后内存对其,最终sizeof为12吗?哪位解释下,为什么结果是16?
这不是C++标准的东西吧, 这依赖于编译器自身
标准上应该12,但是g++显示的好像不是12,而是16,所以,不明白g++对象模型是怎么样的呀?所以想请教下的呀!
标准从来没规定应该是多少。
你说的“g++对象模型”根本不是标准的内容,标准本身不是哪个具体的编译器厂商定的。
标准里有个关于大小的规定倒是,就是sizeof(X)不能为零,但是被另一个STD-LY类型(之前叫POD类型)继承S的时候,sizeof(S)可以只考虑S自身的成员占用情况(而让X在其中不占任何实际空间)
但是lz的例子里,Y、Z虚继承于X,结果Y、Z、A都已经不是STD-LY类型了,所以sizeof具体应该为多少,标准已经没有相应的规定了,只要是固定大小就行,编译器设计者可以自己决定
#12
补充一下,虚继承、虚函数的实现方式目前有虚表、二叉树、hash表等方式,现在主流的编译器多使用虚表这种实现方式、讨论的也比较多,但不要认为是标准规定了用虚表实现。虚表不是标准里的内容、标准也没规定该用什么方式实现虚函数、虚继承这些。
#13
哎,楼主《深度探索C++对象模型》基本白看了,竟然把virtual继承无视了。