Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > Контроль множестова копий указателя


Автор: mmortall 1.2.2012, 14:32
Есть класс-менеджер Монстров, который создает обекты тыпа Монстр. Указатель на Монстра передается в атакующие турели, которые стреляют в монстра. Помимо этого указатель на него 
передается в менеджер мультиплеера, в селектор (выделение мышкой) и возможно дальнейшее расширение списка классов, где необходим указатель на монстра. 

Когда монстр убит какой ни будь турелью, она оповещает все классы о том, что монстр умер и в них указатель обноляется. Далее монстр выгружается из памяти. 
Мне такая система не нравится. Думаю что было бы идеально иметь какой ни будь контейнер, который бы инкапсулировал этот указатель + методы типа valid/invalid. 
Но в стандартный библиотеке я такого не нашел. 
Реф каунтиг тут делать не нужно, т.к. классы не равнозначны и основным держателем указателя есть Менеджер Монстров.

Такая задача вроде часто встречается, подскажите, как элегантно и красиво её решить? Спасибо.

Автор: newbee 1.2.2012, 15:04
Я в таких случаях использую систему событий. Регистрирую событие man_down, подписываю на него всех заинтересованных сторон (колбэки), и примерно так использую:
Код

void remove_monster(struct moster *monster){
 process_action(man_down, monster);
 free(monster);}


Можешь посмотреть в сторону готовых решений: сигналы-слоты в boost или Qt.

Автор: bsa 1.2.2012, 15:50
Если пишешь на С++ (на С это тоже можно, но геморройней), то можно сделать иначе :
1. вместо простого указателя на монстра передается "умный с подсчетом ссылок" (например, boost::shared_ptr или std::shared_ptr в С++11).
2. класс монстр содержит свойство "жизнь" (думаю, он уже содержит).
3. когда монстр убит, то свойство "жизнь" принимает определенное значение (например: 0)
4. перед тем как выстрелить турель проверяет, а жив ли монстр по данному указателю, если не жив, то указатель удаляется из списка целей турели.

Особенность умного указателя в том, что когда будет "потерян" последний указатель, указывающий на объект, то объект будет уничтожен. Таким образом, монстр будет удален из памяти тогда, когда все заинтересованные объекты удалят его из своих списков.

Автор: mes 1.2.2012, 17:06
Цитата(mmortall @  1.2.2012,  13:32 Найти цитируемый пост)
Реф каунтиг тут делать не нужно, т.к. классы не равнозначны 

посмотрите weak_ptr к shared_ptr..

Цитата(mmortall @  1.2.2012,  13:32 Найти цитируемый пост)
Есть класс-менеджер Монстров, который создает обекты тыпа Монстр. Указатель на Монстра передается в атакующие турели, которые стреляют в монстра. Помимо этого указатель на него 
передается в менеджер мультиплеера, в селектор (выделение мышкой) и возможно дальнейшее расширение списка классов, где необходим указатель на монстра. 

не слишком ли переусложнено ?


Автор: Albor 2.2.2012, 11:48
Цитата(mmortall @  1.2.2012,  13:32 Найти цитируемый пост)
Указатель на Монстра передается в атакующие турели, которые стреляют в монстра. Помимо этого указатель на него 
передается в менеджер мультиплеера, в селектор (выделение мышкой) и возможно дальнейшее расширение списка классов, где необходим указатель на монстра. 

А почему не передавать указатель по ссылке или указатель на указатель? Тогда все объекты будут работать с оригиналом данных

Автор: xvr 2.2.2012, 11:56
Еще можно сделать доступ к Мострам по уникальному ID из Менеджера Монстров. Когда Монстр создается, ему присваивается ID (например 64х битное число), которое уже не переиспользуется (например банальный счетчик). Для доступа к Монстру он запрашивается у Менеджера Монстров по ID, и Менеджер возвращает указатель или NULL (если Монстр был уничтожен)

Автор: bsa 2.2.2012, 12:04
xvr, это несколько дольше работает, чем с указателем smile 

Автор: xvr 2.2.2012, 12:24
Цитата(bsa @ 2.2.2012,  12:04)
xvr, это несколько дольше работает, чем с указателем smile

Это да, но гарантирует централизованное управление временем жизни Монстров. И не требует введения для Монстров состояния Зомби (уже умерли, но еще не удалили  smile )

Автор: borisbn 2.2.2012, 12:33
Цитата(Albor @  2.2.2012,  11:48 Найти цитируемый пост)
А почему не передавать указатель по ссылке или указатель на указатель? Тогда все объекты будут работать с оригиналом данных

Пожалуй, самый быстрый (как по реализации, так и по времени выполнения) вариант, но, если потребуется потокобезопасное обращение к объекту, то могут возникнуть трудности.
Цитата(xvr @  2.2.2012,  11:56 Найти цитируемый пост)
Еще можно сделать доступ к Мострам по уникальному ID из Менеджера Монстров

Вариант, возможно, и медленнее, но довольно несложно делается потокобезопасное обращение. Что-то типа такого
Код
Monster * MonstersManager::lock( long long ID );
void MonstersManager::unlock( long long ID );

А вообще - интересная тема. Спасибо ТСу.


Автор: boostcoder 2.2.2012, 12:57
много лет мечтаю написать какую-нить игрулину. эх...мечты-мечты smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)