Почему деструктор базовых классов должен быть виртуальным? - PullRequest
13 голосов
/ 03 мая 2011

в C ++: почему деструктор базовых классов должен быть виртуальным?

Ответы [ 5 ]

36 голосов
/ 03 мая 2011

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

Это сделало бы невозможным применение пустой оптимизации базового класса и могло бы умножить размер классов в 16 раз, чем это было бы без virtual на распространенных платформах.

Деструктор virtual необходим при delete объекте с динамическим типом DerivedClass с помощью указателя типа BaseClass*. virtual заставляет компилятор связывать информацию в объекте, позволяя ему выполнять деструктор производного класса. Пропуск virtual в таком случае вызывает неопределенное поведение.

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

8 голосов
/ 03 мая 2011

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

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

class derived : public base {
public:
  ~derived() { }  // Inherits the virtual designation
};

int main(void)
{
  base *b = new derived;

  delete b;
}

Производный деструктор будет вызываться только , если базовый деструктор является виртуальным.

Как указывает Магнус, вам не обязательно делать это, если вы не пользуетесь полиморфизмом. Тем не менее, я пытаюсь выработать привычку объявлять все мои деструкторы виртуальными. Это защищает меня от случая, когда я должен был объявить их виртуальными, но забыть сделать это. Как указывает Йоханнес, эта привычка может налагать небольшое пространство и снижать производительность, когда виртуальное обозначение не требуется.

4 голосов
/ 03 мая 2011

Для подобных ситуаций:

class A
{
    virtual ~A();
};

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

A *a = new B(); //legal, since it's a downcast
delete a; //Unless the destructor is virtual, ~A() is called here instead of ~B().
3 голосов
/ 03 мая 2011

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

1 голос
/ 03 мая 2011

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

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