Преобразование структуры POD в производный тип

Работая над устаревшим проектором, я наткнулся на следующую схему:
структура 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адрес совпадает с адресом объекта d типа DerivedFromPOD, как и для базового класса POD?

1

Решение

Это, безусловно, не гарантирует работу в целом (попробуйте добавить виртуальную функцию в производный класс), и это формально неопределенное поведение. (Я тоже не понимаю, как struct может использоваться для передачи данных по сети. Разные машины будут представлять это по-разному.)

2

Другие решения

DerivedFromPOD* Указатель можно безопасно привести в PODType* указатель.
Таким образом, мы уверены, что макет наследственного PODType в памяти то же самое.

Тем не менее, при приведении в противоположном направлении, DerivedFromPOD может быть составлен в памяти с некоторыми данными компилятора, тогда PODType данные, а затем некоторые дополнительные данные компилятора.

Если вы используете приведение в стиле C, или static_cast<> для этого приведения компилятор предположит, что вы знаете, что вы делаете, и настроит адрес указателя так, чтобы PODType часть DerivedFromPOD правильно укажет на хороший район.

Однако не пытайтесь использовать методы, которые будут обращаться к другим данным из DerivedFromPOD поскольку они не будут правильными в памяти.

В частности, не используйте виртуальные методы в качестве VMT (Таблица виртуальных методов) не там.

1

По вопросам рекламы [email protected]