Если каждый класс имеет виртуальный деструктор?

голоса
45

Java и C # поддерживают понятие классов , которые не могут быть использованы в качестве базовых классов с finalи sealedключевыми словами. В C ++ , однако не существует хороший способ предотвратить класс от является производным от которого уходит автор класса с дилеммой, должен каждый класс имеет виртуальный деструктор или нет?


Edit: Так как C ++ 11 это уже не так, вы можете указать , что класс final.


С одной стороны , давая объект виртуальный деструктор означает , что он будет иметь vtableи , следовательно , потребляют 4 (или 8 на 64 - битных машинах) дополнительные байты в-объект для vptr.

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

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

Некоторые люди думают , что вам нужно явно причину не использовать виртуальный деструктор (как подтекст этого вопроса ) , а другие говорят , что вы должны использовать их только тогда , когда у вас есть основания полагать , что ваш класс должен быть производным от, что же ты думать?

Задан 09/12/2008 в 19:56
источник пользователем
На других языках...                            


8 ответов

голоса
53

Каждый абстрактный класс должен либо иметь,

  • защищенный деструктор, или,
  • виртуальный деструктор.

Если у вас есть публичный, не виртуальный деструктор, что не хорошо, так как она позволяет пользователям удалять через этот указатель на объект производного. Так как все мы знаем, что это неопределенное поведение.

Для класса не предназначен для удаления через указатель на него, нет никаких причин , чтобы иметь виртуальный деструктор. Это не только тратить ресурсы, но что более важно , что бы дать пользователям неправильный намек. Просто подумайте о том, что дерьмовый смысл было бы дать std::iteratorвиртуальный деструктор.

Ответил 09/12/2008 в 20:06
источник пользователем

голоса
26

Вопрос в том , действительно, вы хотите , чтобы обеспечить соблюдение правил о том , как ваши классы должны быть использованы? Зачем? Если класс не имеет виртуальный деструктор, кто использует класс знает , что он не предназначен быть производным от, и какие ограничения применяются , если вы попробуете его в любом случае. Разве это не достаточно хорошо?

Или вам нужен компилятор , чтобы бросить тяжелую ошибку , если кто - нибудь осмелится сделать то , что вы не ожидали?

Дайте классу виртуальный деструктор, если вы собираетесь для людей, чтобы извлечь из него. В противном случае нет, и предположим, что кто-нибудь с помощью кода достаточно умен, чтобы использовать ваш код правильно.

Ответил 09/12/2008 в 20:18
источник пользователем

голоса
8

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

Ответил 09/12/2008 в 20:04
источник пользователем

голоса
4

Проверьте эту статью из Herb Sutter :

Принцип # 4: класс деструктор базы должен быть общим и виртуальным, или защищенными и невиртуальным.

Ответил 10/12/2008 в 14:08
источник пользователем

голоса
2

Я бы «нет» к общему вопросу. Не каждый класс нуждается в один. Если вы знаете , что класс не должен быть унаследован от, то нет никакой необходимости брать на себя незначительные накладные расходы. Но если есть шанс, быть на безопасной стороне и положить один там.

Ответил 09/12/2008 в 19:58
источник пользователем

голоса
0

Базовый класс становится абстрактным классом, когда он содержит по крайней мере одну чистую виртуальную функцию. Если база не иметь виртуальный деструктор и производный (на основе базы) делает, то вы можете спокойно уничтожить Производный объект через производный указатель на объект, но не через указатель базового объекта.

Ответил 12/05/2010 в 21:04
источник пользователем

голоса
0

Я добавлю, что были времена, когда я почесал голову на некоторое время на деструкторов не вызывался, когда я забыл виртуальный в родительском или детском классе. Я думаю, я знаю, что искать, что сейчас, хотя. :)

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

Ответил 09/12/2008 в 20:14
источник пользователем

голоса
-3
include<iostream> using namespace std;

class base {
    public: base() {
        cout << "In base class constructor" << endl;
    }

    virtual ~base() {
        cout << "in base class destuctor" << endl;
    }
};

class derived : public base {
    public: derived() {
        cout << "in derived class constructor" << endl;
    }

    ~derived() {
        cout << "in derived class destructor" << endl;
    }
};

int main() {
    base *b; // pointer to the base
    class b = new derived; // creating the derived class object using new
    keyword;
    delete b;
    return 0;
}
Ответил 01/01/2016 в 13:52
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more