Я нашел этот вопрос, спросив то же самое, однако только 'новой' части ответили, таким образом, здесь идет снова.
Почему оператор delete требуется быть статичным? Так или иначе это не имеет смысла. Новый оператор имеет смысл, точно так же, как конструктор не может быть виртуальным, ни один не может новый оператор. Однако деструктор может (и если) быть виртуальным при использовании наследования для разрешения разрушения используемых объектов (посредством полиморфизма) как базовый класс.
Я понимаю, что, когда оператор delete называют, объект был уже уничтожен, таким образом, не 'это' существует. Все же это все еще имеет смысл, с помощью того же обоснования, как с виртуальным деструктором, чтобы иметь оператор delete соответствуют новому оператору, который создал объект.
Это - то, что я имею в виду
class A
{
public:
virtual ~A() {}
};
class B : public A
{
public:
void* operator new (size_t sz);
void operator delete (void* ptr, size_t sz);
};
теперь, если мы делаем
A *ptr = new B();
delete ptr; // <-- fail
Оператор delete A (значение по умолчанию) нужно было назвать, так как это статично, и это не знало (ни для чего кроме тривиального случая здесь) во время компиляции, какой оператор delete является корректным.
Однако я сделал маленькую тестовую программу с кодом выше (просто malloc/free в новых / операторах delete, и оператор печати в удаляет), и скомпилировал его с помощью g ++. Выполнение его вполне неожиданно произвело вывод в операторе delete B.
Мой (реальный) вопрос - это: там некоторая неявная 'виртуальность' к оператору delete? Действительно ли это только статично в смысле no-this-pointer? Или это - просто g ++ функция?
Я начал просматривать спецификацию C++, но я должен признать, я был битом, разбитым ею, таким образом, любая ценившая справка.
Ответ в правилах языка действительно в 12.5 [class.free].
Если вы удаляете с помощью указателя на базовый класс, то деструктор должен быть виртуальным, иначе вы получите неопределенное поведение. В противном случае реализация должна определить динамический тип удаляемого объекта.
12.5/4 говорит, что когда delete
не имеет префикса ::
, тогда функция освобождения определяется путем поиска delete
в контексте динамического типа. виртуальный деструктор. Это обеспечивает поиск, подобный виртуальному, даже несмотря на то, что оператор delete
всегда является статической
функцией-членом.
Необработанное выделение и освобождение происходит концептуально вне времени существования объекта, поэтому к тому времени, когда должна быть вызвана функция освобождения, уже не существует объекта для обеспечения механизма виртуального поиска, но правила поиска гарантируют, что оператор delete
имеет механизм динамического (виртуального облегченного!) Поиска. Это означает, что оператор delete может быть статическим
без потери связи с динамическим типом исходного объекта.
Оператор delete
предназначен только для освобождения памяти, а память освобождается для объекта самого производного класса в целом - за одно действие - точно так же Как и в случае с оператором new
, он выделяется для всего самого производного объекта класса - объекта класса, переданного в качестве аргумента в конструкцию new Class
.
Вот почему, когда вы выполняете delete ptr;
, оператор delete
всегда вызывается только один раз для фактического самого производного класса удаляемого объекта и данных о том, какой класс он выводится либо из vtable, если виртуальный деструктор присутствует, либо из типа указателя, если виртуального деструктора нет. Поэтому в операторе delete
нет неявной виртуальности - вся виртуальность заканчивается в точке вызова деструктора.