2010-01-19 2 views
2

Я пишу игру и сопроводительный движок на C++. Двигатель в значительной степени зависит от автоматизации с использованием простого встроенного языка сценариев. Скрипты могут создавать классы объектов, определять на них прослушиватели событий и создавать экземпляры из них. В настоящее время экземпляр должен быть привязан к глобальному идентификатору сценария, чтобы сохранить его существование. Очевидным результатом этого является отсутствие анонимных объектов, которые, безусловно, будут наиболее распространены.Поддержание std :: set <boost :: shared_ptr>

В настоящее время экземпляры управляются с использованием std::set<Instance*, spatial_sort>, где spatial_sort - это функтор, который сортирует экземпляры по положению, для визуализации и обнаружения столкновений. Экземпляры удаляются и повторно вставлены в каждый фрейм, используя их текущую позицию в качестве подсказки, исходя из предположения, что они вряд ли будут перемещаться в течение пятидесятой секунды. Если в экземпляре установлен флаг dead, он удаляется из набора. Конструкторы и деструктор Instance вызывают insert(this) и erase(this) соответственно.

Для того, чтобы разрешить анонимные экземпляры, я хочу изменить набор на std::set<boost::shared_ptr<Instance>, spatial_sort>, что позволит Instance делиться владением экземплярами и сохранять их существование до тех пор, пока они не уничтожат самих себя. К сожалению, поскольку призывы к insert() необходимо поместить в конструктор, shared_from_this() не будет работать для получения shared_ptr до Instance. Не имеет значения, что Instance уже наследует от boost::enable_shared_from_this<> через свой базовый класс.

Может ли кто-нибудь рекомендовать подходящее обходное решение?

Edit:

Я сделал то, что должен был делать в первую очередь, и разделить поведение Instance класса на два класса: Instance и Reference. Выражение new SomeClass в сценарии затем возвращает Reference к новому Instance. Сами объекты Instance никогда не управляются с помощью shared_ptr, поэтому они несут ответственность за самоубийство в ответ на подходящее событие, например, конец анимации, конец уровня и т. Д.

Спасибо за помощь! Рефакторинг является таким же хорошим решением, как любой, если он просто работает.

ответ

2

Вы можете добавить статический метод Instance, который затем используется для создания новых объектов, а также делает административный материал, как добавить его в набор:

static Instance* create(int something) { 
    boost::shared_ptr<Instance> sptr(new Instance(something)); 
    instanceset.insert(sptr); 
    return sptr.get(); 
} 

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

Подробнее об этом см. Также в разделе C++ FAQ Lite о "Dynamic binding during initialization", который напрямую не связан, но использует ту же технику для ограничения ограничений на использование виртуальных функций в конструкторах.

+3

Еще лучше, верните shared_ptr вместо исходного. – rlbond

+0

В настоящий момент я возился с этим решением; в принципе create() только когда-либо вызывается для создания анонимных экземпляров и инициализирует экземпляр с установленным «анонимным» флагом. Если этот флаг не установлен, экземпляр по умолчанию выполняет insert() для shared_ptr для себя с нулевым делетером. В настоящее время я пытаюсь отследить загадочное исключение bad_weak_ptr, возникшее в результате изменения. –

+0

* «Если этот флаг не установлен, экземпляр по умолчанию выполняет insert() для shared_ptr для себя» * Я не уверен, что именно вы делаете, но похоже, что он снова запустится в проблему, не может вызывать 'shared_from_this()' во время построения. Также обратите внимание, что 'shared_from_this()' работает только в том случае, если объект фактически хранится в shared_ptr где-то. Например, 'shared_from_this()' на статически выделенном экземпляре не будет работать. – sth

Смежные вопросы