sha*_*oth 50 c++ inheritance sizeof language-lawyer
假设我有一个带有一些成员变量且没有虚函数的基类:
class Base {
int member;
};
Run Code Online (Sandbox Code Playgroud)
以及从非虚拟方式派生Base并且没有新成员变量的派生类,再次没有虚函数:
class Derived : Base {
};
Run Code Online (Sandbox Code Playgroud)
显然sizeof(Derived)不能小于sizeof(Base).
被sizeof(Derived)要求等于sizeof(Base)?
Tri*_*dle 18
从5.3.2 [expr.sizeof]
应用于类时,结果[of
sizeof]是该类对象中的字节数,包括在数组中放置该类型对象所需的任何填充.最派生类的大小应大于零(1.8).
从1.8 [intro.object]
除非它是位字段(9.6),否则最派生的对象应具有非零大小并且应占用一个或多个存储字节.基类子对象可以具有零大小.POD类型(3.9)的对象应占用连续的存储字节.
并注意:
由于虚基类和对基类子对象的不太严格的填充要求,基类子对象的实际大小可能小于将sizeof应用于子对象的结果.
将这些放在一起,我认为它告诉你的是,sizeof除了结果大于零之外,你无法保证可能会告诉你什么.事实上,它似乎甚至没有保证sizeof(Derived) >= sizeof(Base)!
Ker*_* SB 13
没有这样的要求.
我能想到的语言中唯一相关的部分是,每个对象,无论是否完整,以及是否是大多数派生的,都有一个身份,由一对地址和类型给出.参看 C++ 11 1.8/6:
如果一个是另一个的子对象,或者如果至少一个是零大小的基类子对象并且它们是不同类型的,则不是位字段的两个对象可以具有相同的地址; 否则,他们应有不同的地址.
因此,示例中派生最多的对象和基础子对象必须具有不同的标识.
对于编译器来说,同时给出两者Base和Derived大小都是有意义的1,但这不是强制性的.如果Base尺寸为1729并且Derived尺寸为2875,那将是可以接受的.
有趣的问题.我有一个例子,其中用一个额外的字段派生类是大小相同的作为空基类. (这应该是一个评论,但是太大了;请接受其他答案之一,尽管如果它很有趣,欢迎赞成.)
考虑一下这个简单的C++程序:
class A {};
class B : public A {
int m_iInteger;
};
int _tmain(int argc, _TCHAR* argv[])
{
printf("A: %d\r\n", sizeof(A));
printf("B: %d\r\n", sizeof(B));
printf("int: %d\r\n", sizeof(int));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
你期望输出sizeof(int)是什么,如果是4?也许是这样的:
A: 0
B: 4
int: 4
Run Code Online (Sandbox Code Playgroud)
?
我的编译器 - Embarcadero C++ Builder 2010 - 给出了输出:
A: 8
B: 8
int: 4
Run Code Online (Sandbox Code Playgroud)
换句话说,在派生类中添加额外字段不会使派生类更大.
有一些关于兼容性选项零长度空基类的帮助文件主题的原因.
通常,类的大小至少为一个字节,即使该类没有定义任何数据成员.设置此选项时,编译器会忽略内存布局的未使用字节以及任何派生类的总大小; 空基类不会占用派生类中的空间.默认= False
对于此编译器,具有默认编译器设置的类的大小似乎是8个字节,而不是一个,实际上更改此代码示例的此设置无效.
您可能还会发现有关基类大小和上述优化的文章很有趣.它讨论了为什么类必须具有至少一个字节的大小,优化的作用,以及深入研究成员函数的表示等:
实际上,该标准要求物体的尺寸永远不应为零; 它还要求在派生对象中,基类的成员应出现在派生类的用户声明数据成员之前.但是,基类子对象不被视为完整对象.因此,可以在不违反规则的情况下从派生对象中删除基类子对象.换句话说,在对象t中,S和x的偏移可能重叠......
请阅读文章,了解该报价的完整背景.
| 归档时间: |
|
| 查看次数: |
2299 次 |
| 最近记录: |