2017-02-22 10 views
4

Часто рекомендуется использовать deleteLater() вместо обычного delete в Qt. Однако это приводит к проблеме оборванных объектов: они помечены для удаления, но все еще отображаются в дочерних списках, возвращаемых Qt API. (Так как это поведение является серьезным противоречием, мое быстро развивающееся чувство Qt quirks заставило меня проверить его. Они делают.) Итак, есть ли идиоматический способ отслеживать такие объекты? Я мог бы, конечно, использовать раствор однорангового какКак отслеживать объекты, запланированные для последующего удаления?

class DeleteLaterable 
{ 
public: 
    void markForDeletion() { mMarked = true; } 
    bool isMarked() const { return mMarked; } 
private: 
    bool mMarked = false; 
}; 

и публично наследовать все от него, но он открывает совершенно другую банку виртуальных червей наследования. Любые лучшие идеи?

+4

Удалить ребенка, а затем 'deleteLater()'. – dtech

+2

Будет ли это работать, если вы просто вызываете setParent (nullptr) при планировании удаления объекта? –

+0

Спасибо, ребята. Пойдем, выберем его из соответствующих списков вручную. – sigil

ответ

2

Начиная с Qt 5.8, невозможно отслеживать объекты, запланированные для удаления из коробки.

Вызов deleteLater() просто отправьте сообщение (QDeferredDeleteEvent) на объект цели. Поскольку нет способа получить список ожидающих событий, вы не можете знать, какой объект получит QDeferredDeleteEvent.

Чтобы достичь того, чего вы хотите, есть несколько решений:

  1. Используйте «DeleteLaterManager» класс с «DeleteObject (QObject *)» функцию, которая будет вызывать deletelater() и следить за объектом пока не будет удален.
  2. Reimplement QAbstractEventDispatcher и отслеживать события типа QEvent::DeferredDelete.
  3. Используйте специальный класс событий типа QEvent::DeferredDelete и вместо звонка deleteLater() звоните QCoreApplication::postEvent().

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

На стороне примечания, почему «это поведение является серьезным контратаком»? В документации deleteLater() просто указывается, что объект будет назначен для удаления, почему было бы затронуто отношение родителя/ребенка?

+0

@ Benjamin T Это нелогично, потому что это не так, как обычно. После того, как вы пометили файл для удаления, например, OS API не перечисляет его вместе с обычными файлами. Сам файл может быть удален намного позже и после нескольких процедур на уровне системы - все, кроме окончательного, обратимого - но из жизненного цикла файла бизнес-логики заканчивается, когда вы устанавливаете флаг «удалить эту вещь». – sigil

+0

@sigil Объект не «помечен» для удаления, он «запланирован» для удаления. Вызов «deleteLater» не меняет объект, он просто говорит вам, что в какой-то момент в будущем он будет удален. Вообще говоря, вы не должны предполагать, что API будет делать больше, чем задокументировано: «deleteLater» не является «markAsDeleted», и нигде в документации Qt не говорится, что «о удаленном объекте не указаны». –