Russian Qt Forum
Ноябрь 26, 2024, 02:02
Добро пожаловать,
Гость
. Пожалуйста,
войдите
или
зарегистрируйтесь
.
Вам не пришло
письмо с кодом активации?
1 час
1 день
1 неделя
1 месяц
Навсегда
Войти
Начало
Форум
WIKI (Вики)
FAQ
Помощь
Поиск
Войти
Регистрация
Russian Qt Forum
>
Forum
>
Программирование
>
Общий
>
Обобщить взаимодействие
Страниц: [
1
]
Вниз
« предыдущая тема
следующая тема »
Печать
Автор
Тема: Обобщить взаимодействие (Прочитано 6798 раз)
Igors
Джедай : наставник для всех
Offline
Сообщений: 11445
Обобщить взаимодействие
«
:
Май 09, 2016, 11:18 »
Добрый день
Данная ситуация возникает уже третий раз, значит пришла пора обобщать. Рассмотрим на одном наборе классов (другие аналогичны)
Есть довольно развесистый класс
Trigger
все экземпляры которого хранятся в глобальном контейнере. Этот контейнер предъявляется юзеру в UI, и только юзер отвечает за создание и удаление экземпляров. Напр юзер может создать Trigger неиспользуемый никогда, и наоборот, удалить используемый.
Другой класс
Node
просто использует назначенный ему экземпляр Trigger вызывая его методы (клиент). Разумеется нужно отследить удаление используемого с возможным undo, а также (де)сериализацию Node. Пока нет др классов-клиентов Trigger, но их появление возможно.
Как бы Вы это решали?
Спасибо
Записан
Old
Джедай : наставник для всех
Offline
Сообщений: 4350
Re: Обобщить взаимодействие
«
Ответ #1 :
Май 09, 2016, 11:29 »
У каждого триггера свой уникальный id (uint64_t). Нода хранит этот id. При необходимости взаимодействия с объектом триггер, нода получает указатель на него по сохраненному id. Если возвращается nullptr, то триггер удален пользователем. id удаленного триггера нода продолжает помнить, т.е. триггер может вернуться по undo. При сохранении нод можно проверить наличие триггера и сохранить не старый id, а 0 (для ноды не установлен триггер).
Записан
Racheengel
Джедай : наставник для всех
Offline
Сообщений: 2679
Я работал с дискетам 5.25 :(
Re: Обобщить взаимодействие
«
Ответ #2 :
Май 09, 2016, 11:42 »
Класс-менеджер триггеров (это Ваш контейнер) должен хранить мапу <id, *CTrigger>.
id - зависит от того, как хотите триггеры идентифицировать (число, строка и т.д.)
При желании при удалении триггера он может испускать сигнал "я помер".
Получить триггер - что то типа такого:
CTrigger* triggerPtr = TriggerManager::GetTrigger(auto id);
if (triggerPtr)
// триггер жив
else
// не было такого
«
Последнее редактирование: Май 09, 2016, 11:45 от Racheengel
»
Записан
What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.
COVID не волк, в лес не уйдёт
Igors
Джедай : наставник для всех
Offline
Сообщений: 11445
Re: Обобщить взаимодействие
«
Ответ #3 :
Май 09, 2016, 12:14 »
Цитата: Old от Май 09, 2016, 11:29
У каждого триггера свой уникальный id (uint64_t).
Да. Причем я начал просматривать др (смежные) классы - и тоже использование id смотрится резонно.
Цитата: Racheengel от Май 09, 2016, 11:42
CTrigger* triggerPtr = TriggerManager::GetTrigger(auto id);
Так примерно и есть для 2 уже имеющихся реализаций, вот я и хочу обобщиться чтобы не налипал повторяющийся код xxxManager.
Записан
Igors
Джедай : наставник для всех
Offline
Сообщений: 11445
Re: Обобщить взаимодействие
«
Ответ #4 :
Май 10, 2016, 09:50 »
Обдумываю..
- стоит ли хранить ID в самом классе (напр Trigger) или пусть оно будет чисто ключом контейнера? (думаю последнее).
- как назначать "очередное" ID? Счетчик? (не уверен)
- стоит ли прилагать усилия чтобы контейнер (и только он) мог создавать/удалять экземпляры? (не уверен)
- оставлять ли в мапе "пустые" слоты (id + null)? (думаю да). Нужен ли метод(ы) для чистки пустых слотов?
- что делать с "append" (слияние 2 контейнеров)? Пока только одна такая операция и можно пробежаться по использующим (заткнуть эту дыру). Стоит ли замахиваться на большее?
Записан
Old
Джедай : наставник для всех
Offline
Сообщений: 4350
Re: Обобщить взаимодействие
«
Ответ #5 :
Май 10, 2016, 10:54 »
Цитата: Igors от Май 10, 2016, 09:50
- стоит ли хранить ID в самом классе (напр Trigger) или пусть оно будет чисто ключом контейнера? (думаю последнее).
Он как бы не нужен самому триггеру, но бывает так, что функции/методу которому передается указатель на триггер, необходимо узнать его id.
Обойти это можно передавая таким функциям кроме указателя и его текущий id.
Цитата: Igors от Май 10, 2016, 09:50
- как назначать "очередное" ID? Счетчик? (не уверен)
максимальный id триггера в контейнере +1
Цитата: Igors от Май 10, 2016, 09:50
- стоит ли прилагать усилия чтобы контейнер (и только он) мог создавать/удалять экземпляры? (не уверен)
Зачем прилагать усилия, что-бы добавить ограничения?
Цитата: Igors от Май 10, 2016, 09:50
- оставлять ли в мапе "пустые" слоты (id + null)? (думаю да). Нужен ли метод(ы) для чистки пустых слотов?
Да пусть будут. Объект триггера все равно не будет разрушаться, а будет перемещаться в undo-стек и легко может вернуться обратно.
И методы для очистки не нужны. Человек все равно не сможет настолько изуродовать map частыми добавлениями-удалениями.
Цитата: Igors от Май 10, 2016, 09:50
- что делать с "append" (слияние 2 контейнеров)? Пока только одна такая операция и можно пробежаться по использующим (заткнуть эту дыру). Стоит ли замахиваться на большее?
Если такая операция есть, придется реализовать. Я бы ее скорее всего сделал внешней утилитой.
Записан
Igors
Джедай : наставник для всех
Offline
Сообщений: 11445
Re: Обобщить взаимодействие
«
Ответ #6 :
Май 10, 2016, 11:38 »
Цитата: Old от Май 10, 2016, 10:54
максимальный id триггера в контейнере +1
Т.к. ID ключ, то ID последнего +1, но тогда я беру обязательство не удалять пустые слоты (или по крайней мере последний). Ничего плохого в этом пока не вижу, вот насколько оно выгодно.
Цитата: Old от Май 10, 2016, 10:54
Да пусть будут. Объект триггера все равно не будет разрушаться, а будет перемещаться в undo-стек и легко может вернуться обратно.
Обязан (требование проекта) поддерживать "честное" удаление, undo пишется на диск. При этом пустые слоты будут потеряны после undo. Конечно хочется использовать методы записи/чтения также и для undo.
Цитата: Old от Май 10, 2016, 10:54
Если такая операция есть, придется реализовать. Я бы ее скорее всего сделал внешней утилитой.
ID 2 контейнеров слить/объединить не вопрос, но что делать с использующими 2-й (чьи ID изменились)? Тут можно размахнуться намного ширше: хранить не только "личное" ID, но и ID(s) кто ссылается на него + на кого он сам. Это дает интересные возможности, но может оказаться слишком большим/неадекватным.
Записан
Old
Джедай : наставник для всех
Offline
Сообщений: 4350
Re: Обобщить взаимодействие
«
Ответ #7 :
Май 10, 2016, 11:51 »
Цитата: Igors от Май 10, 2016, 11:38
Т.к. ID ключ, то ID последнего +1
Ну если триггеры отсортированы по id (как в map), то последнего +1
Цитата: Igors от Май 10, 2016, 11:38
но тогда я беру обязательство не удалять пустые слоты (или по крайней мере последний). Ничего плохого в этом пока не вижу, вот насколько оно выгодно.
Мое мнение - нет нужды их удалять. Пользователь все равно не сможет руками на создавать огромное число триггеров.
Цитата: Igors от Май 10, 2016, 11:38
Обязан (требование проекта) поддерживать "честное" удаление, undo пишется на диск. При этом пустые слоты будут потеряны после undo. Конечно хочется использовать методы записи/чтения также и для undo.
Ну пусть храниться на диске, по клику мышки он в любой момент может стать объектом.
Цитата: Igors от Май 10, 2016, 11:38
ID 2 контейнеров слить/объединить не вопрос, но что делать с использующими 2-й (чьи ID изменились)? Тут можно размахнуться намного ширше: хранить не только "личное" ID, но и ID(s) кто ссылается на него + на кого он сам. Это дает интересные возможности, но может оказаться слишком большим/неадекватным.
Я бы размахивался.
Записан
_Bers
Бывалый
Offline
Сообщений: 486
Re: Обобщить взаимодействие
«
Ответ #8 :
Май 17, 2016, 00:38 »
Цитата: Igors от Май 09, 2016, 11:18
Добрый день
Данная ситуация возникает уже третий раз, значит пришла пора обобщать. Рассмотрим на одном наборе классов (другие аналогичны)
Есть довольно развесистый класс
Trigger
все экземпляры которого хранятся в глобальном контейнере. Этот контейнер предъявляется юзеру в UI, и только юзер отвечает за создание и удаление экземпляров. Напр юзер может создать Trigger неиспользуемый никогда, и наоборот, удалить используемый.
Другой класс
Node
просто использует назначенный ему экземпляр Trigger вызывая его методы (клиент). Разумеется нужно отследить удаление используемого с возможным undo, а также (де)сериализацию Node. Пока нет др классов-клиентов Trigger, но их появление возможно.
Как бы Вы это решали?
Спасибо
std::shared_ptr/ std::weak_ptr
Записан
Igors
Джедай : наставник для всех
Offline
Сообщений: 11445
Re: Обобщить взаимодействие
«
Ответ #9 :
Май 17, 2016, 10:14 »
Цитата: _Bers от Май 17, 2016, 00:38
std::shared_ptr/ std::weak_ptr
Это решает лишь одну задачу - облегчается удаление
Node
Trigger.
«
Последнее редактирование: Май 18, 2016, 09:31 от Igors
»
Записан
_Bers
Бывалый
Offline
Сообщений: 486
Re: Обобщить взаимодействие
«
Ответ #10 :
Май 18, 2016, 01:25 »
Цитата: Igors от Май 17, 2016, 10:14
Цитата: _Bers от Май 17, 2016, 00:38
std::shared_ptr/ std::weak_ptr
Это решает лишь одну задачу - облегчается удаление Node.
это решает проблему: "кто о ком знает, и кто кем владеет".
в частности - проблему времени жизни Trigger
Записан
Igors
Джедай : наставник для всех
Offline
Сообщений: 11445
Re: Обобщить взаимодействие
«
Ответ #11 :
Май 18, 2016, 10:08 »
Цитата: _Bers от Май 18, 2016, 01:25
это решает проблему: "кто о ком знает, и кто кем владеет".
Думаю это было столь же ясным/решенным и без всяких вумных указателей
Реализовал контейнер по ID, ну пока еще плотно его не использовал (пока надо дописать UI и все такое). Интересно обсудить:
- решил пока оставить "Т" полностью свободным, т.е. никакие его методы/члены в контейнере не юзаются. Да, рухнет если самостоятельно удалить Т* сидящее в контейнере - впрочем то же самое и для банального вектора указателей
- свободные "слоты" - все-таки решил удалять (кроме последнего)
- вот интересно хранение/восстановление "связок по ID". Пока использую примитивно, напр Node хранит ID Trigger'а. Теперь при его удалении не надо бегать обнулять указатель на него в Node. При undo и (де)сериализации также все складывается хорошо. Прикидывал как сделать хранение ID "внешним". Хранить Node в контейнере ID - явно в масть, экземпляры Node могут ссылаться друг на друга. Но дальше неясно. Напр как Node должен получать указатель на Trigger (без члена mTriggerID)?
Записан
Страниц: [
1
]
Вверх
Печать
« предыдущая тема
следующая тема »
Перейти в:
Пожалуйста, выберите назначение:
-----------------------------
Qt
-----------------------------
=> Вопросы новичков
=> Уроки и статьи
=> Установка, сборка, отладка, тестирование
=> Общие вопросы
=> Пользовательский интерфейс (GUI)
=> Qt Quick
=> Model-View (MV)
=> Базы данных
=> Работа с сетью
=> Многопоточное программирование, процессы
=> Мультимедиа
=> 2D и 3D графика
=> OpenGL
=> Печать
=> Интернационализация, локализация
=> QSS
=> XML
=> Qt Script, QtWebKit
=> ActiveX
=> Qt Embedded
=> Дополнительные компоненты
=> Кладовая готовых решений
=> Вклад сообщества в Qt
=> Qt-инструментарий
-----------------------------
Программирование
-----------------------------
=> Общий
=> С/C++
=> Python
=> Алгоритмы
=> Базы данных
=> Разработка игр
-----------------------------
Компиляторы и платформы
-----------------------------
=> Linux
=> Windows
=> Mac OS X
=> Компиляторы
===> Visual C++
-----------------------------
Разное
-----------------------------
=> Новости
===> Новости Qt сообщества
===> Новости IT сферы
=> Говорилка
=> Юмор
=> Объявления
Загружается...