在处理遗留项目时,我遇到了以下模式:POD结构用于通过网络传输数据 .
struct PODType {
// some data
int data;
};
在接收器侧,数据被接收到POD类型的对象中 . 稍后,从PODType派生一个类,并将接收到的对象与C样式强制转换为派生类,以使用一些访问数据的方法 .
class DerivedFromPOD: public PODType {
public:
// some methods
int f(int x) {return data+x;}
protected:
// some methods
};
PODType pod;
receive(&pod);
DerivedFromPOD* d = (DerivedFromPOD*)&pod;
int i = d->f(10);
派生类具有公共和受保护的方法,因此它不再是POD . 我知道这是滥用继承,但它已经在代码库中存在了很长时间 .
我想知道这是否可以保证从标准的角度来看(C 03或C 98) . 派生类没有任何自己的数据成员或虚函数,但我不确定它是否保证内存布局是相同的,因为一个是POD而另一个不是 . 是否强制编译器安排DerivedFromPOD,使 d.data
的地址与DerivedFromPOD类型的对象d的地址相同,就像POD基类一样?
2 回答
它's certainly not guaranteed to work in general (try adding a virtual function to the derived class), and is formally undefined behavior. (I also don't看看
struct
如何用于帮助通过网络传输数据 . 不同的机器将以不同的方式表示 . )DerivedFromPOD*
指针可以安全地转换为PODType*
指针 . 所以我们确信内存中继承的PODType
的布局是一样的 .但是,当在相反的方向上进行转换时,
DerivedFromPOD
可以在内存中用一些编译器数据组成,然后是PODType
数据,然后是一些额外的编译器数据 .如果您正在使用C样式转换或
static_cast<>
进行此转换,编译器将假设您知道您正在做什么并调整指针地址,以便DerivedFromPOD
的PODType
部分将正确指向好区域 .但是,不要尝试使用将从
DerivedFromPOD
访问其他数据的方法,因为它们在内存中不正确 .特别是,不要使用任何虚拟方法,因为VMT(虚拟方法表)不存在 .