Я не знаю, как точно озаглавить этот вопрос, поэтому вот объяснение:
У меня есть собственный виджет, который выдает сигнал с пользовательским объектом, созданным из пользовательского ввода, когда завершает редактирование, например,
void GGActionEditor::finishEditing() {
GGAction act;
// Set up according to user input
emit actionChanged(act);
}
В этом коде получатели, которые подключены к сингалу, могут сохранить копию этого объекта или обработать его любым удобным способом, и виджет может об этом забыть.
Но как справиться с такой ситуацией, когда виджет можно построить Различные типы объектов из класса иерачры? Подобно:
void GGActionEditor::finishEditing() {
GGAction *pAct;
// Create and set up according to user input, e.g.
if (...) pAct = new GGSpecialAction;
else pAct = new SimpleAction;
emit actionChanged(pAct);
}
Как лучше всего справиться с жизненным циклом объекта в такой ситуации? Виджет не может знать, принимает ли какой-либо получатель объект Action. Кроме того, если подключено несколько приемников, никто из них не знает, принял ли другой объект параметр …
В «лучшем» случае это может привести к утечке; но это также может привести к тому, что параметр будет удален несколько раз.
Обновить:
Еще немного информации о моей реальной ситуации, однако я также заинтересован в общих решениях:
Переданный объект будет сохранен получателем и сохранен в доменной модели приложения. Модель позаботится об его удалении позже.
Простое решение состоит в том, чтобы просто обработать этот случай как «простой» случай значения, описанный выше. Однако, если к нему вообще не подключены приемники, объект будет протекать; и нет 100% гарантии, что только 1 получатель будет делать это (в моей реальной логике приложения это будет иметь место, но это не может быть ни проверено, ни применено таким образом).
Я придумал несколько возможных решений и заинтересован в любых комментариях или дополнениях:
bool*
к сигналу, который указывает, принял ли какой-либо приемник действие. Получатель знает, что он не сможет его обогнать, если значение будет истинным. Также отправитель знает, должен ли он удалить объект, если его не получил ни один получатель. Но совершенно случайно, какой получатель возьмет объект в порядке поступления. И это портит интерфейс …clone
метод к классам:clone
создаст копию конкретного подкласса.GGIActionReceiver
класс и назначить не более 1 экземпляра в GGActionEditor
, Этот экземпляр является единственным правомочным объектом, который принимает объект Action. Другие могут все еще сигнализироваться, но они не должны обогнать указатель. Таким образом, отправитель также знает, должен ли объект быть удален (не указан получатель)Одним из вариантов здесь является использование общего владения через std :: shared_ptr<> или какой-то другой механизм подсчета ссылок. Таким образом, объект будет жить до тех пор, пока это кому-нибудь нужно.
Обычная модель владения Qt не совсем работает, потому что вы не можете быть уверены, сколько пользователей сигналов захотят стать владельцем одного и того же объекта.
В зависимости от вашей логики совместное владение может привести к замкнутым циклам и разрыву тех, которые могут быть вынуждены сделать дырки в абстракции или двух.
Убедитесь, что не смешиваете владение Qt с shared_ptr — ваши QObjects не должны иметь родителей.
Других решений пока нет …