Бьерн Страуструп.
Язык программирования С++
175
void operator delete(void*, size_t);
virtual
~employee();
};
Даже пустой деструктор решит нашу проблему:
employee::~employee() { }
Теперь освобождение памяти будет происходить в деструкторе (а в нем размер известен), а любой
производный от employee класс также будет вынужден определять свой деструктор (тем самым будет
установлен нужный размер), если только пользователь сам не определит его. Теперь следующий
пример пройдет правильно:
void f()
{
employee* p = new manager; //
теперь без проблем
delete
p;
}
Размещение происходит с помощью (созданного транслятором) вызова
employee::operator new(sizeof(manager))
а освобождение с помощью вызова
employee::operator delete(p,sizeof(manager))
Иными словами, если нужно иметь корректные функции размещения и освобождения для производных
классов, надо либо определить виртуальный деструктор в базовом классе, либо не использовать в
функции освобождения параметр size_t. Конечно, можно было при проектировании языка
предусмотреть средства, освобождающие пользователя от этой проблемы. Но тогда пользователь
"освободился" бы и от определенных преимуществ более оптимальной, хотя и менее надежной
системы.
В общем случае, всегда есть смысл определять виртуальный деструктор для всех классов, которые
действительно используются как базовые, т.е. с объектами производных классов работают и, возможно,
удаляют их, через указатель на базовый класс:
class X {
//
...
public:
//
...
virtual
void
f();
// в X есть виртуальная функция, поэтому
// определяем виртуальный деструктор
virtual
~X();
};
Достарыңызбен бөлісу: