2015-04-25 2 views
1

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

Исходный код использует некоторые материалы 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(); 
} 
+0

Это совершенно неправильный подход при выполнении ООП. Вы должны использовать указатель 'Base *', и он может указывать на любой производный класс. – Barmar

+0

Вопрос не в том, как получить доступ к данным с помощью указателя или нет. Вопрос состоял в том, если безопасно, что макет в иерархии безопасен для использования общих данных в иерархии. Исходный код должен использовать данные внутри производных классов. Представленный код предназначен только для просмотра эффекта. – Klaus

ответ

1

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

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

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

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

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

0

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

Объединение может иметь только один активный элемент; построение Derived1 делает недействительным то, что было раньше.

Смежные вопросы