2010-01-19 9 views
2

J'écris un jeu et un moteur d'accompagnement en C++. Le moteur repose fortement sur l'automatisation en utilisant un langage de script intégré simple. Les scripts peuvent créer des classes d'objets, définir des écouteurs d'événements sur ceux-ci et produire des instances à partir d'eux. À l'heure actuelle, une instance doit être liée à un identificateur global de script afin de préserver son existence. Le résultat évident de ceci est qu'il ne peut y avoir d'objets anonymes, qui seront de loin les plus communs.Maintenir un std :: set <boost :: shared_ptr>

Actuellement, les instances sont gérées à l'aide d'un std::set<Instance*, spatial_sort>, où spatial_sort est un foncteur qui trie les instances par position, pour le rendu et la détection de collision. Les instances sont supprimées et réinsérées chaque image en utilisant leur position actuelle comme indice, en supposant qu'elles ne vont pas bouger beaucoup dans un cinquantième de seconde. Si un indicateur dead est défini dans l'instance, il est effacé de l'ensemble. Les constructeurs Instance et destructeur invoquent insert(this) et erase(this), respectivement. Pour autoriser les instances anonymes, je souhaite changer l'ensemble en std::set<boost::shared_ptr<Instance>, spatial_sort>, ce qui permettrait à Instance de partager la propriété des instances et de préserver leur existence jusqu'à ce qu'elles se détruisent elles-mêmes. Malheureusement, parce que les appels à insert() doivent être placés dans le constructeur, shared_from_this() ne fonctionnera pas pour obtenir un shared_ptr au Instance. Il n'importe pas du tout que Instance hérite déjà de boost::enable_shared_from_this<> via sa classe de base.

Quelqu'un peut-il recommander une solution de contournement appropriée?

Edit:

je fait ce que j'aurais dû faire en premier lieu, et de diviser le comportement de la classe Instance en deux classes: Instance et Reference. L'expression new SomeClass dans un script renvoie ensuite un Reference à un nouveau Instance. Les objets Instance eux-mêmes ne sont jamais gérés en utilisant un shared_ptr, ils sont donc responsables du suicide en réponse à un événement approprié, par exemple la fin de l'animation, la fin du niveau, etc.

Merci pour l'aide! Le refactoring est aussi une bonne solution que n'importe quel autre si cela fonctionne.

Répondre

2

Vous pouvez ajouter une méthode statique à Instance que vous utilisez ensuite pour créer de nouveaux objets et qui fait aussi les choses administratives comme l'ajout à l'ensemble:

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

Si vous voulez faire de cette seule façon pour construire un objet de cette classe, vous pouvez aussi rendre le constructeur normal privé ou protégé. Pour plus d'informations, consultez également l'entrée C++ FAQ Lite sur "Dynamic binding during initialization", qui n'est pas directement liée mais utilise la même technique pour contourner les restrictions sur l'utilisation des fonctions virtuelles dans les constructeurs.

+3

Mieux encore, renvoyez le shared_ptr au lieu d'un raw. – rlbond

+0

Je suis en train de jouer avec cette solution en ce moment; Fondamentalement, create() est seulement appelé pour créer des instances anonymes, et initialise une Instance avec un ensemble d'indicateurs "anonymes". Si cet indicateur n'est pas défini, l'instance exécute par défaut un insert() d'un shared_ptr sur lui-même avec un suppresseur nul. À l'heure actuelle, j'essaie de retrouver la mystérieuse exception bad_weak_ptr résultant du changement. –

+0

* "Si ce drapeau n'est pas défini, l'Instance exécute par défaut un insert() d'un shared_ptr sur lui-même" * Je ne sais pas exactement ce que vous faites, mais il semble que cela se reproduise dans le problème que vous ne peut pas appeler 'shared_from_this()' pendant la construction. Notez également que 'shared_from_this()' ne fonctionne que si l'objet est réellement stocké dans un sharedptr quelque part. Par exemple 'shared_from_this()' sur une instance allouée statiquement ne fonctionnera pas. – sth

Questions connexes