在处理遗留项目时,我遇到了以下模式: 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基类一样?
答案 0 :(得分:2)
它当然不能保证一般工作(尝试向派生类添加虚函数),并且是正式未定义的行为。 (我也不知道如何使用struct
来帮助通过网络传输数据。不同的机器将以不同的方式表示它。)
答案 1 :(得分:1)
DerivedFromPOD*
指针可以安全地转换为PODType*
指针。
所以我们确信内存中继承的PODType
的布局是相同的。
然而,当以相反的方向进行转换时,DerivedFromPOD
可以在内存中用一些编译器数据组成,然后是PODType
数据,然后是一些额外的编译器数据。
如果您正在使用C样式转换,或者static_cast<>
进行此转换,编译器将假设您知道您正在做什么并调整指针地址,以便PODType
部分DerivedFromPOD
将正确指向好区域。
但是,不要尝试使用可以访问DerivedFromPOD
中其他数据的方法,因为它们在内存中不正确。
特别是,不要使用任何虚拟方法,因为VMT (虚拟方法表)不存在。