Правильный способ наследования от виртуального класса с не-виртуальным родителем продолжен - PullRequest
0 голосов
/ 07 января 2012

Мой вопрос основан на этом вопросе: Правильный способ наследования от виртуального класса с не-виртуальным родителем .

Правильно ли я понимаю, что в случае, описанном ввопрос, три и две части нового выделенного объекта протекают, потому что они не разрушены?

Источник:

#include <iostream>

struct One
{
    ~One() {
        std::cout << "~One()\n";
    }
};

struct Two : One
{
    virtual ~Two() {
        std::cout << "~Two()\n";
    }

    virtual void test() = 0;
};

struct Three : Two
{
    virtual ~Three() {
        std::cout << "~Three()\n";
    }

    virtual void test() {
        std::cout << "Three::test()\n";
    }
};

int main()
{
    Two* two = new Three;
    two->test();

    One* one = two;
    delete one;
}

1 Ответ

1 голос
/ 07 января 2012

Да, это правильно. Определение утечки памяти - это ситуация, когда вы не можете удалить что-то, что вы создали (и за время жизни которого вы, следовательно, отвечаете за управление).

Как указывают ответы на этот вопрос, delete one вызывает неопределенное поведение (которое в большинстве случаев, вероятно, приведет к обычной утечке старой памяти, но вещи могут быть такими же плохими, как носовые демоны ), поскольку тип времени выполнения указанного объекта не соответствует его статическому (объявленному) типу, а статический тип не имеет виртуального деструктора.

Применимый раздел из стандарта C ++:

§5.3.5 / 3: В первом альтернативном варианте (удаление объекта), если статический тип операнда отличается от его динамического типа, статический тип должен быть базовым классом динамического типа операнда и статического типа. должен иметь виртуальный деструктор или поведение не определено.

Решение - объявить все деструкторы virtual или не удалять объекты через указатель на One.

...