将POD结构转换为派生类型

时间:2014-05-13 11:52:30

标签: c++ struct casting legacy-code memory-layout

在处理遗留项目时,我遇到了以下模式: 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 个答案:

答案 0 :(得分:2)

它当然不能保证一般工作(尝试向派生类添加虚函数),并且是正式未定义的行为。 (我也不知道如何使用struct来帮助通过网络传输数据。不同的机器将以不同的方式表示它。)

答案 1 :(得分:1)

DerivedFromPOD*指针可以安全地转换为PODType*指针。 所以我们确信内存中继承的PODType的布局是相同的。

然而,当以相反的方向进行转换时,DerivedFromPOD可以在内存中用一些编译器数据组成,然后是PODType数据,然后是一些额外的编译器数据。

如果您正在使用C样式转换,或者static_cast<>进行此转换,编译器将假设您知道您正在做什么并调整指针地址,以便PODType部分DerivedFromPOD将正确指向好区域。

但是,不要尝试使用可以访问DerivedFromPOD中其他数据的方法,因为它们在内存中不正确。

特别是,不要使用任何虚拟方法,因为VMT (虚拟方法表)不存在。