Russian Qt Forum
Апрель 07, 2020, 19:08 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2 3 ... 6   Вниз
  Печать  
Автор Тема: Qt + вумные указватели  (Прочитано 3234 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 10740


Просмотр профиля
« : Февраль 14, 2020, 13:56 »

Добрый день

Предлагаю выделить ветку обсуждения в новую тему.

А если бы всё-таки решили в Qt использовать умные указатели и контейнеры std, то как бы хранили список детей (children) для QObject?

Например, так

Для такой огромной кодовой базы родом из 90-х, умные указатели действительно мало что дадут. Полагаю, Qt до скончания своих веков будет на голых указателях жить. Если менять на умные нормально, там много чего переделывать придётся, и это будет уже совсем другой Qt. Но это не значит, что надо опустить руки и ничего не делать Улыбающийся.

Лично я, мягко говоря, не уверен что это вообще стоит делать. Ну вот напр QTreeWidgetItem. Им вроде бы "владеет" QTreeWidgetView, но всякий желающий может его спокойно грохнуть (delete item). А можно айтем и "забрать" (take). Пусть это не шедевр инженерной мысли, но такая организация данных мне кажется вполне разумной и каких-то претензий к ней у меня нет.

Что мы хотим улучшить? Не понимаю. Затевать здесь гемор с юниками мне кажется абсолютно ни к чему. Думается срабатывает "фетиш" типа "голый/raw = плохо", никаких др оснований не видно.

Ваше мнение?
Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 821



Просмотр профиля
« Ответ #1 : Февраль 14, 2020, 14:10 »

Затевать здесь гемор с юниками мне кажется абсолютно ни к чему.

Юники нужны, чтобы не было тем подобных этой: Непонятное удаление cell widget.

Собственно в этих двух методах:
Код
C++ (Qt)
template<class T>
void adoptChild(T *child);
 
template<class T>
T* adoptChild(std::unique_ptr<T> child);
меня и смущает, что по голому указателю передаётся владение. Хотя в других случаях с голым указателем - нет, например, QLabel::setBuddy(QWidget *buddy). Может это исключение из правил, но в глаза бросилось.
Записан

Пока сам не сделаешь...
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 10740


Просмотр профиля
« Ответ #2 : Февраль 14, 2020, 14:57 »

Юники нужны, чтобы не было тем подобных этой: Непонятное удаление cell widget.
Так это вроде "наоборот", жалуется на отсутствие ф-ционала "take". Уникальность владения лишь усугубит такие проблемы.

Ну хорошо, допустим (ценой немалых усилий) мы все же добились что айтемы стали юниками. Что это дает? Теперь мы уж точно знаем кто ими владеет!! (а так не знали Улыбающийся) Разве невозможны данные которые многие (или всякий) может удалить? Что в этом плохого и почему с этим надо бороться?  Улыбающийся 
Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 821



Просмотр профиля
« Ответ #3 : Февраль 14, 2020, 15:35 »

Так это вроде "наоборот", жалуется на отсутствие ф-ционала "take". Уникальность владения лишь усугубит такие проблемы.

Так сначала-то хотелось "оставить" объект себе, а юник такое явно запретил бы, и вопроса: "Почему это происходит?" не возникло. Сразу возник бы второй вопрос: "назад не отобрать уже никак?", но это уже другая история Улыбающийся.
Записан

Пока сам не сделаешь...
Авварон
Джедай : наставник для всех
*******
Online Online

Сообщений: 3025


Просмотр профиля
« Ответ #4 : Февраль 14, 2020, 16:05 »

меня и смущает, что по голому указателю передаётся владение. Хотя в других случаях с голым указателем - нет, например, QLabel::setBuddy(QWidget *buddy). Может это исключение из правил, но в глаза бросилось.

А это не смущает?
Код:
new MyObject(this);

Особенно весело когда идешь в код MyObject, а там
Код:
explicit MyObject(MyObjectManager *manager, QObject *parent = nullptr);

Я уже объяснил в соседнем топике, что adoptChild от указателя нужен в переходный период потому что позволяет посадить обезьянку и сделать s/child->setParent(parent)/parent->adoptChild(child)/g не трогая при этом типы указателей.
Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 821



Просмотр профиля
« Ответ #5 : Февраль 14, 2020, 16:52 »

А это не смущает?
Код:
new MyObject(this);

Особенно весело когда идешь в код MyObject, а там
Код:
explicit MyObject(MyObjectManager *manager, QObject *parent = nullptr);

В текущей версии меня столько всего смущает, что об этом и говорить не стоит Улыбающийся.

Я уже объяснил в соседнем топике, что adoptChild от указателя нужен в переходный период потому что позволяет посадить обезьянку и сделать s/child->setParent(parent)/parent->adoptChild(child)/g не трогая при этом типы указателей.

Раз надо так надо, что тут сказать Улыбающийся.
Записан

Пока сам не сделаешь...
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 821



Просмотр профиля
« Ответ #6 : Февраль 17, 2020, 11:19 »

Ну вот напр QTreeWidgetItem. Им вроде бы "владеет" QTreeWidgetView, но всякий желающий может его спокойно грохнуть (delete item). А можно айтем и "забрать" (take). Пусть это не шедевр инженерной мысли, но такая организация данных мне кажется вполне разумной и каких-то претензий к ней у меня нет.

Сначала надо попросить владельца отдать объект (take/release/и т.п.), и если он отпустит его на свободу, тогда можно делать с этим объектом что угодно, в том числе удалять. А не так, что кто угодно, когда угодно, мог удалить любой объект.

Ну хорошо, допустим (ценой немалых усилий) мы все же добились что айтемы стали юниками. Что это дает? Теперь мы уж точно знаем кто ими владеет!! (а так не знали Улыбающийся) Разве невозможны данные которые многие (или всякий) может удалить? Что в этом плохого и почему с этим надо бороться?  Улыбающийся

Едите Вы на автомобиле, и внезапно "многий" удаляет двигатель, а "всякий" - тормоза Улыбающийся. Как Вам понравится такая поездка? Нужно ли с этим бороться?
Записан

Пока сам не сделаешь...
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 10740


Просмотр профиля
« Ответ #7 : Февраль 17, 2020, 17:00 »

Сначала надо попросить владельца отдать объект (take/release/и т.п.), и если он отпустит его на свободу, тогда можно делать с этим объектом что угодно, в том числе удалять. А не так, что кто угодно, когда угодно, мог удалить любой объект.
Это разумные соображения "вообще", но не конкретно для айтема. Попробуйте написать такое удаление - получится полная фигня

Едите Вы на автомобиле, и внезапно "многий" удаляет двигатель, а "всякий" - тормоза Улыбающийся. Как Вам понравится такая поездка? Нужно ли с этим бороться?
Опять в общем случае - да, конкретно - нет. В данном случае работоспособность автомобиля (QTreeWidget) гарантируется, т.к. он отслеживает удаление. Заметим что такая простая "ассоциативная связь" никаким вумным указателем не выражается.

Мне кажется очевидным что "юник" и "шаред" - всего лишь 2 случая, пусть популярных, но пригодных далеко не всегда. Не нужно пытаться их впихнуть всегда и везде. Если для выражения данной сущности они не подходят (как в случае айтема), то или свой велик или голый указатель, ничего "такого уж плохого" в нем нет
Записан
Авварон
Джедай : наставник для всех
*******
Online Online

Сообщений: 3025


Просмотр профиля
« Ответ #8 : Февраль 17, 2020, 18:07 »

Это разумные соображения "вообще", но не конкретно для айтема. Попробуйте написать такое удаление - получится полная фигня

Пробовал. И уже дважды постил на форуме. Получается отлично.
Записан
Авварон
Джедай : наставник для всех
*******
Online Online

Сообщений: 3025


Просмотр профиля
« Ответ #9 : Февраль 17, 2020, 18:20 »

Опять в общем случае - да, конкретно - нет. В данном случае работоспособность автомобиля (QTreeWidget) гарантируется, т.к. он отслеживает удаление. Заметим что такая простая "ассоциативная связь" никаким вумным указателем не выражается.

TreeItem уникально владеет своими детьми. QTreeWidget уникально владеет rootItem. Что тут не выражается вумным указателем??
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 10740


Просмотр профиля
« Ответ #10 : Февраль 17, 2020, 19:05 »

Пробовал. И уже дважды постил на форуме. Получается отлично.
Не сказал бы. Ну может я чего-то не понял.
Код
C++ (Qt)
ItemObserverPointer item = ...;  //  как-то получили айтем
...
// теперь его надо удалить (напр юзер нажал Del)
// delete item;  // так нельзя
// а тогда как ???
Это надо брать парента, проверять его на null и звать remove, так, что ли? И разве после этого item потеряет валидность? Как-то коряво
TreeItem уникально владеет своими детьми. QTreeWidget уникально владеет rootItem.
Владеет - да, удаление QTreeWidget вызовет удаление всех айтемов. Но зачем навязывать уникальность если по смыслу ее нет? Напр диалог/окно (владелец QTreeWidget) что, не может удалять?
Что тут не выражается вумным указателем??
Вектор чайлдов, нужно "вычернуть" айтем из него - этого вумники не делают. И все равно приходится иметь remove для этого, а перенести его вызов в caller'a усложняет код но ровным счетом ничего не меняет.
Записан
Авварон
Джедай : наставник для всех
*******
Online Online

Сообщений: 3025


Просмотр профиля
« Ответ #11 : Февраль 17, 2020, 19:21 »

Это надо брать парента, проверять его на null и звать remove, так, что ли? И разве после этого item потеряет валидность? Как-то коряво
Парент есть по определению всегда. Если это не рут, который вы не можете удалить по определению=)

Либо у вас observer_ptr и вы айтемом не владеете (а значит и удалить не можете).
Либо у вас unique_ptr и вы c айтемом можете делать что хотите.

Да, в моем коде нет метода "достать" айтем, но его очень легко написать и пока не было нужно.

Владеет - да, удаление QTreeWidget вызовет удаление всех айтемов. Но зачем навязывать уникальность если по смыслу ее нет? Напр диалог/окно (владелец QTreeWidget) что, не может удалять?

Как нет уникальности, когда она есть? Если айтем в модели\вьюхе, то модель\вьюха уникально этим айтемом владеет.
Если айтем не в модели\вьюхе, то делайте с ним что хотите, хоть голым указателем пользуйтесь, но извольте "передать владение" когда будете добавлять в модель\вьюъу.

Вектор чайлдов, нужно "вычернуть" айтем из него - этого вумники не делают. И все равно приходится иметь remove для этого, а перенести его вызов в caller'a усложняет код но ровным счетом ничего не меняет.

Вот вам TreeModelItem, вполне себе "вумник" который умеет "вычернивать" айтемы. Совсем уже программисты обленились, дерево написать ленятся, всё им на блюдечке подавай.
« Последнее редактирование: Февраль 17, 2020, 19:41 от Авварон » Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 821



Просмотр профиля
« Ответ #12 : Февраль 17, 2020, 19:44 »

Похоже грядёт очередной заход на Деревянный айтем  Веселый.
Записан

Пока сам не сделаешь...
ssoft
Бывалый
*****
Offline Offline

Сообщений: 495


Просмотр профиля
« Ответ #13 : Февраль 18, 2020, 07:25 »

Похоже грядёт очередной заход на Деревянный айтем  Веселый.

Как раза хотел о том же сказать). Вот же пример иерархии tree-example, который мы разбирали. Возьмите в качестве значения unique_ptr< QObject> и будет счастье. К слову, эта реализация у нас хорошо зашла для широкого использования.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 10740


Просмотр профиля
« Ответ #14 : Февраль 18, 2020, 13:21 »

Либо у вас observer_ptr и вы айтемом не владеете (а значит и удалить не можете).
Либо у вас unique_ptr и вы c айтемом можете делать что хотите.
Возьмем самую банальную ситуацию. Есть окно, в нем список/listbox и рядом кнопка del которая становится активной если в listbox есть выбранные айтемы. При этом список будет стандартным классом, чем-то типа QTreeWidget, т.е. владеть-то он владеет, но что (какие айтемы) удалять - без понятия. Это чисто ф-ционал окна (напр случилось нажатие del). Окну и нужно удалять. И, как я понял, это придется делать так
Код
C++ (Qt)
void DeleteItem( ItemObserverPointer & item )
{
auto parent = item->parent();
assert(parent);
parent->remove(item);
item.reset();
}
 
Ну как-то не очень удобно (особенно по сравнению с простецким "delete item"). И кстати не видно где/как пресекается удаление непотопляемого root'a

Как нет уникальности, когда она есть? Если айтем в модели\вьюхе, то модель\вьюха уникально этим айтемом владеет.
Если под "уникальностью" подразумевается и "только вью удаляет" то (очень) простой пример выше показывает что это очевидно не так. Да, вью должно остаться валидным после удаления, но лучше это отслеживать в самом айтеме чем грузить caller'a всякий раз.

Ф-ционал "copy" - ушли в отказ, ф-ционал "take" - тоже не видно. Я понимаю что это скорее попытка написать "без всяких указателей/адресов". Теоретически это интересно, но с чисто утилитарной точки зрения (типа "поюзать") неудобства очевидны, а вот выгод не видно. Хотя не исключено что мнение старого ретрограда предвзято  Улыбающийся
Записан
Страниц: [1] 2 3 ... 6   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.119 секунд. Запросов: 22.