Деструктор не вызывается при удалении пустого указателя

У меня 3 класса

class A
{
    A();
    virtual ~A();
}
class B : public A
{
    B();
    ~B();
}
class C
{
    void *obj;
    C() : obj(nullptr) {}
    ~C() { if (obj) delete obj; }
}

когда я использую класс C как контейнер для любого потомка класса A и попробуй удалить C пример. A, B не разрушен деструктор это нормально? Что такое решение?

C* instance = new C();
instance.obj = new B();
//Magic
delete instance; // A and B destructor is not called

3 ответа

Решение

Удаление указателя на несовместимый тип (в том числе void) дает неопределенное поведение.

Каково решение?

  • используйте правильный тип: либо тип, который вы указали newили базовый класс, если у него есть виртуальный деструктор; или же
  • использование std::shared_ptr<void>инициализировано из std::shared_ptr<correct_type>: его удалитель сделает правильную вещь.

В этом случае, похоже, вы можете просто хранить A* скорее, чем void*, так как вы говорите, что это должен быть "контейнер для любого потомка класса A".

Между прочим, нет необходимости проверять, является ли указатель нулевым, перед его удалением.

Вы удаляете void*, так delete не знает, что это B* поэтому деструктор не может быть вызван. Вы должны использовать указатель класса, если хотите, чтобы при удалении вызывался деструктор.

Например, это все классы, которые могут быть C obj расширить А, затем использовать A*,

Да, удаление требует определенного типа.

Другие вопросы по тегам