Pergunta

While working on a legacy projectr I came across the following pattern: a POD struct is used to transfer data over the network.

struct PODType {
    // some data
    int data;
};

On the receiver side, the data is received into an object of the POD type. Later on, a class is derived from the PODType and the received object is casted with a C-style cast into the derived class to use some methods accessing the data.

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);

The derived class has public and protected methods, so it is not a POD anymore. I know that this is an abuse of inheritance, but it has been in the code base for a long time.

I am wondering if that is guaranteed to work from a standard point of view (C++03 or C++98). The derived class does not have any own data members or virtual functions, but I am not sure if it guaranteed that the memory layout is identical given that one is POD and the other is not. Is the compiler forced to arrange DerivedFromPOD such that d.data's address is identical to the address of an object d of DerivedFromPOD type, as it is for the POD base-class?

Foi útil?

Solução

It'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 see how a struct can be used to help transfer data over the network. Different machines will represent it differently.)

Outras dicas

A DerivedFromPOD* pointer can be cast safely into a PODType* pointer. So we are assured that the layout of the inherited PODType in memory is the same.

However, when casting in the opposite direction, DerivedFromPOD can be composed in memory with some compiler data, then the PODType data, then some additional compiler data.

If you're using the C-style cast, or static_cast<> for this cast, the compiler will assume you know what you're doing and adjust the pointer address so that the PODType part of the DerivedFromPOD will correctly point to the good area.

However don't try to use methods that will access other data from DerivedFromPOD as they won't be correct in memory.

In particular, don't use any virtual methods as the VMT (Virtual Method Table) is not there.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top