Вызов виртуального метода из деструктора - обходной путь? - PullRequest
7 голосов
/ 02 февраля 2012

Мне нужно объявить метод финализации finalize() для всех потомков базового класса Base, который должен вызываться во время уничтожения, и я намеревался вызвать pure virtual void Base::finalize() = 0 из ~Base(), но c ++ запрещает такиевещь.Итак, мой вопрос

Как мы можем обязать потомков выполнять завершающую работу правильно и предварительно определенным образом?

Этот код не может быть скомпилирован:

#include <QDebug>
class Base {
        public:
            Base(){}
            virtual ~Base(){
                qDebug("deleting b");
                finalize();
            }
            virtual void finalize() = 0;

    };

class A : public Base
    {
    public:
        A(){}
        ~A(){}
        void finalize(){qDebug("called finalize in a");}
    };

    int main(int argc, char *argv[])
    {
        Base *b = new A;
        delete b;
    }

Если ясделать Base::finalize() не чисто виртуальным, он вызывается из ~Base() без отправки дочернему элементу, так как он уже уничтожен.

Я могу вызвать finalize () из деструктора ребенка, но вопрос в том, как заставить это сделать.Другими словами, мой вопрос: возможно ли заставить людей, которые будут писать потомков Базового класса, использовать метод финализации, ну, иначе, чем комментировать это в документации?:)

Ответы [ 4 ]

7 голосов
/ 02 февраля 2012

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

Определение виртуальных деструкторов позволяет вызывать деструктор class A при удалении указателя на class Base, указывающего на class A объект

Base* p = new A;
delete p; // Both A and Base destructors are sequencially called! 

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

3 голосов
/ 02 февраля 2012

Вот для чего предназначен виртуальный деструктор:

class A
{
public:
   virtual ~A() {}
};

class B : public A
{
public:
   virtual ~B() {}
};

Когда объект типа B уничтожается независимо от того, является ли указатель на B или указатель на AБудут вызваны оба деструктора.Сначала B::~B(), а затем A::~A().

1 голос
/ 02 февраля 2012

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

0 голосов
/ 02 февраля 2012

Почему бы не использовать деструктор Base?Вот для чего созданы деструкторы.

Сделайте поиск RAII и откройте для себя одну из лучших вещей в c ++.

Большинство людей, привыкших использовать другие языки, должны открыть это.Управление ресурсами в C ++ полностью отличается от большинства других языков программирования

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...