Это, конечно, работает для объектов, созданных new
и когда вызывающий Update
правильно осведомленных о том, что поведение. Но я бы избегал этого. В вашем случае владение явно находится в мире, поэтому я бы уничтожил мир. Объект не создает себя, я думаю, он также не должен удалять себя. Может быть очень удивительно, если вы вызываете функцию «Обновить» на свой объект, но вдруг этот объект уже не существует, и мир не делает ничего из себя (кроме удаления его из своего списка, но в другом фрейме! Обновление объекта не заметит этого).
Некоторые идеи по этому
- Добавить список ссылок на объекты в мире. Каждый объект в этом списке ожидает удаления. Это обычная техника и используется в wxWidgets для закрытых окон верхнего уровня, но все равно может получать сообщения. В режиме простоя, когда все сообщения обрабатываются, обрабатываемый список обрабатывается и объекты удаляются. Я считаю, что Qt следует аналогичной технике.
- Сообщите миру, что объект хочет быть удаленным. Мир будет правильно проинформирован и позаботится о том, что нужно сделать. Возможно, что-то вроде
deleteObject(Object&)
.
- Добавить функцию
shouldBeDeleted
для каждого объекта, который возвращает true, если объект желает удалить его владельцем.
Я бы предпочел вариант 3. Мир назвал бы Update. И после этого он смотрит, должен ли объект быть удален, и может сделать это - или, если он пожелает, он помнит этот факт, добавив этот объект в список ожидающего удаления вручную.
Это боль в заднице, когда вы не можете быть уверены, когда и когда не сможете получить доступ к функциям и данным объекта. Например, в wxWidgets существует класс wxThread, который может работать в двух режимах. Один из этих режимов (называемый «съемным») заключается в том, что если его основная функция возвращается (и ресурсы потока должны быть освобождены), он удаляет себя (чтобы освободить память, занятую объектом wxThread), вместо того, чтобы ждать владельца потока объект для вызова функции ожидания или соединения. Однако это вызывает сильную головную боль. Вы никогда не можете называть какие-либо функции, потому что это могло быть прекращено при любых обстоятельствах, и вы не можете создать его не с новым. Некоторые люди говорили мне, что они очень не любят этого поведения.
Самодельное удаление ссылочного объекта считается запахом, имхо.Давайте сравним:
// bitmap owns the data. Bitmap keeps a pointer to BitmapData, which
// is shared by multiple Bitmap instances.
class Bitmap {
~Bitmap() {
if(bmp->dec_refcount() == 0) {
// count drops to zero => remove
// ref-counted object.
delete bmp;
}
}
BitmapData *bmp;
};
class BitmapData {
int dec_refcount();
int inc_refcount();
};
Сравните с самостоятельным удалением refcounted объектов:
class Bitmap {
~Bitmap() {
bmp->dec_refcount();
}
BitmapData *bmp;
};
class BitmapData {
int dec_refcount() {
int newCount = --count;
if(newCount == 0) {
delete this;
}
return newCount;
}
int inc_refcount();
};
Я думаю, что первое так намного лучше, и я считаю, хорошо продуманные ссылки подсчитывали объекты делают не сделать «удалить это », потому что он увеличивает связь: класс, использующий подсчитанные данные, должен знать и запоминать, что данные удаляют себя как побочный эффект уменьшения числа отсчетов. Обратите внимание, что «bmp» становится, возможно, висящим указателем в деструкторе ~ Bitmap. По-видимому, не делать этого «удалить это» гораздо приятнее здесь.
Ответ на подобный вопрос "What is the use of delete this"
Мне было трудно выбрать приемлемый ответ здесь. Я выбираю это, потому что он описывает проблемы, с которыми я столкнулся (вещи, отличные от мировых ссылок), а также предлагает shared_ptr, который оказался частью моего решения. Благодарю. –
Другая причина, заключающаяся в том, что я ошибаюсь, заключается в том, что она не позволяет создавать объект в стеке вместо кучи. Кроме того, связь с World делает независимое тестирование невозможным. – walrii