我在派生类中遇到了位域问题。
使用g ++编译器,您可以将__attribute__((packed))
分配给一个类,它将打包位域。所以
class A
{
public:
int one:10;
int two:10;
int three:10;
} __attribute__ ((__packed__));
只占用4个字节。到目前为止,这么好 但是,如果你继承了一个类,就像这样
class B
{
public:
int one:10;
int two:10;
} __attribute__ ((__packed__));
class C : public B
{
public:
int three:10;
} __attribute__ ((__packed__));
我希望C类与上面的A类具有相同的内容,同样具有相同的布局,即占用4个字节。但是,C结果占用了5个字节。
所以我的问题是,我做错了什么,如果是的话,那是什么?或者这是编译器的问题?疏忽,真正的错误?
我尝试使用谷歌搜索,但除了Linux和Windows(编译器试图模拟MSVC)之间的区别之外,我还没有真正想出任何东西,我对此并不感兴趣。这只是在Linux上。< / p>
答案 0 :(得分:0)
我认为问题在于B,它不容易成为2.5个字节。它必须至少为3个字节。
理论上,派生类可能可以重用基类中的填充,但我从未见过这种情况。
答案 1 :(得分:0)
想象一下你要求 的可能性。可能出现的副作用或问题是什么?让我们看一下您所拥有的特定示例。还假设采用1字节内存对齐的32位架构。
class A
中有20个连续位可以通过班级成员one
和two
进行处理。对你来说,这是一个非常方便的解决方案。但编译器做了什么才能实现呢?它使用掩码和位移位将位置这些位置到正确的位置。
到目前为止,这么好,似乎简单而且足够安全。
再添加10位。假设有一些非常智能的编译器允许你将这些额外的10位压缩成一个已经使用过的32位字(它们非常适合,不是吗?)。
遇到麻烦:
A* derived = new B; // upcast to base class
derived->one = 1;
derived->two = 2;
// what is the value of derived->three in this context?
// Especially taking into account that a compiler is free to do all sorts
// of optimizations when generating code for class A
由于上述内容,类为class A
成员和class B
成员使用不同且可单独寻址的内存位置那些10位“溢出”到下一个可寻址存储器位置 - 下一个字节。
当您考虑多重继承时会出现更多麻烦 - 在派生类中排列位的一种真实方式是什么?