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

Я написал этот тестовый код, который использует три типа: struct One - это обычный тип без виртуальных членов, struct Two : One имеет чисто виртуальную функцию и виртуальный деструктор, а struct Three : Two реализует Two. интерфейс.

#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;
}

Неудивительно, что вывод был это:

Три :: тест ()
~ One ()

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

Ответы [ 4 ]

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

delete one вызывает неопределенное поведение, поскольку динамический тип объекта не соответствует статическому типу, а статический тип не имеет виртуального деструктора.

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

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

Единственное «исправление» - не удалять объекты через указатель на One.

Если это частая проблема или нет, зависит от того, как используются ваши классы. Например, стандартная библиотека содержит структуры типа unary_function без виртуального деструктора, но мы вряд ли когда-либо увидим, что она используется неправильно, как это.

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

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

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

Вы должны быть осторожны и сделать деструктор виртуальным Некоторые компиляторы предупреждают об этом.

...