#include <iostream>
using namespace std;
struct A{
virtual void f(){};
int a;
char ch;
};
struct B : public A{
char d;
};
struct C{
double dd;
int a;
char ch;
};
struct D : public C{
char d;
};
int main(){
B b;
D d;
cout<<"b="<<sizeof(b)<<endl;
cout<<"d="<<sizeof(d)<<endl;
}
为什么b和d的结果不同?实际结果如下:
b=16
d=24
我认为每个成员相对于结构体变量地址的偏移量恰好是该成员数据类型大小的倍数,而最终大小是成员中最大数据类型大小的倍数。在存在继承的情况下,基类成员始终出现在派生类成员之前。此外,即使使用字节对齐,派生类成员也不会占用为基类保留的填充字节。换句话说,一旦基类的大小确定,这些字节就归基类独占,不能被派生类的成员使用。那么为什么 sizeof(b) 是 16 而不是 24?
您所说的有关继承基类的结构大小的所有内容都是正确的。但是,您还没有做(并且应该)是检查两个(不同的)基类的大小。
我可以在重现您的大小值的平台上编译您给定的代码(即 MSVC,针对 32 位 Windows);在这种情况下,我添加了几行来显示基类的大小:
// Earlier code as yours ...
int main() {
B b;
D d;
cout << "b=" << sizeof(b) << endl;
cout << "d=" << sizeof(d) << endl;
cout << "A=" << sizeof(A) << endl;
cout << "C=" << sizeof(C) << endl;
return 0;
}
输出:
b=16
d=24
A=12
C=16
我们看到问题了!
struct A
有三个字段:一个函数指针(显然是32位,这里),一个int
(也是4个字节)和一个char
(最后一个字段被填充到4个字节); 3 x 4 字节 = 12 字节;为派生类的(填充的)char
字段添加 4 个字节,您就有 16 个字节。
但是,虽然
struct B
也有三个字段,但第一个字段(double
,大概符合 IEEE)的大小是 8 字节,这将该结构的大小增加到 16 字节,并且从它导出到24。
当我运行为 64 位系统构建的相同代码时,我得到
b
、d
和 A
、C
对的相同大小,因为函数指针的大小相同(8 个字节)作为 double
。