расположение в памяти иерархии классов

Моя цель — создать экземпляры классов иерархии классов, которые совместно используют некоторые общие данные. Я создаю (с объединением) достаточно памяти, чтобы можно было создать самый большой экземпляр в выделенной памяти. Теперь я хочу создать / заменить экземпляр класса и использовать «старые» данные в памяти. Это действительная / легальная операция?

Исходный код использует некоторые MTP-материалы для создания объединения, и цель состоит в том, чтобы использовать эту иерархию классов в качестве ядра реализации конечного автомата. Я показываю только основной код, который содержит проблему.

Я видел, что это проблема, если базовый класс не содержит виртуальные методы, а производные. Это потому, что указатель vtable находится перед памятью (с gcc на x86 / linux).

Простой вопрос: может ли экземпляр производного класса получить доступ к данным из базового класса, если экземпляр базового класса был создан ранее и память используется повторно с экземпляром этого производного класса?

class Base
{
public:
int a;
Base()=default;
Base( int _a):a(_a){}

void Print() { cout << "Value: " << a << endl; }
};

class Derived1: public Base
{
public:
int d;

Derived1(): d( 0x11223344){}
};

union  U
{
U(){}
Base base;
Derived1 derived1;
} u;

int main()
{
memset( &u, 0, sizeof(u));

new (&u) Base(12345678);
u.base.Print();

new (&u) Derived1;
u.base.Print();
}

1

Решение

Нет, это не сработает, потому что сандард говорит:

9,5 / 1: в объединении в любое время может быть активен не более одного не статического члена данных, то есть значение не более одного из
Нестатические члены данных могут быть сохранены в объединении в любое время.

То, что вы пытаетесь сделать, это неопределенное поведение:

new (&u) Derived1;  // RISKY !!!

С новым размещением вы перезаписываете объект, который был в вас раньше, не разрушая его правильно. Затем создание Derived1 в любом случае создаст свою базу. Если каким-то образом вам удастся сохранить старые значения в памяти, это все еще неопределенное поведение: оно может работать или нет, в зависимости от компоновки объекта и реализации вашего компилятора.

1

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

Это неопределенное поведение — оно может работать, но оно не переносимо и не должно зависеть от него.

Союз может иметь только одного активного члена; построение Derived1 делает недействительным то, что было раньше.

0

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