IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Boost C++ Discussion :

utiliser enable_shared_from_this::shared_from_this() dans le constructeur


Sujet :

Boost C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    27
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 27
    Par défaut utiliser enable_shared_from_this::shared_from_this() dans le constructeur
    Bonjour,

    Mon bout de code ci dessous me pose problème .
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class IInteraction : public enable_shared_from_this<IInteraction>  {
       public:
     
          IInteraction( boost::weak_ptr<CPointMechanicsEngine> iEngine ) :
             _Engine( iEngine )
       {
          boost::shared_ptr<CPointMechanicsEngine> Engine(_Engine);
          Engine->AddInteraction( shared_from_this() );
       }
     
       protected:
          boost::weak_ptr<CPointMechanicsEngine> _Engine;
    };
    Le constructeur implémente le fait que IInteraction doit toujours être liée à un CPointMechanicsEngine et que si un IInteraction est lié à un CPointMechanicsEngine, celui ci a un lien vers lui.

    Cependant, lors de l'appel au constructeur de IInteraction, shared_from_this() lève une exception car le pi du shared_ptr est nul. En effet, pn, px, pi ne sont pas initialisés.

    Voici l'appel au constructeur, où CFriction est une classe qui dérive de IInteraction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    boost::shared_ptr<CFriction> Friction (
       new Medias::PointMechanicsEngine::Interactions::CFriction( 
    	PhysicalPoint ,
    	0.3 ,
    	Engine ) );
    Si je fais appel à shared_from_this() dans une méthode après le constructeur ait terminé, il n'y a pas de problème.
    Cependant, cela casse la RAII X(

    Est ce que quelqu'un aurait une solution à mon problème, svp???
    Merci!!!

  2. #2
    Membre expérimenté Avatar de Nogane
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    241
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 241
    Par défaut
    Bonsoir,
    shared_from_this() ne peut pas fonctionner dans le constructeur. Une alternative est de mètre le constructeur en private, et de passer par une méthode static qui fait office de constructeur.
    Par exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    class IInteraction : public enable_shared_from_this<IInteraction>  
    {
    private:
      IInteraction( boost::weak_ptr<CPointMechanicsEngine> iEngine ) :
        _Engine( iEngine )
      {
      }
     
    public:
      static boost::shared_ptr<IInteraction> Create(boost::weak_ptr<CPointMechanicsEngine> iEngine)
      {
         boost::shared_ptr<IInteraction> newPtr(new IInteraction(iEngine));
         boost::shared_ptr<CPointMechanicsEngine> Engine(iEngine);
         Engine->AddInteraction(newPtr);
         return newPtr;
      }
     
    protected:
      boost::weak_ptr<CPointMechanicsEngine> _Engine;
    };

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    27
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 27
    Par défaut
    OK, merci, ça marche nickel!!!

    Par contre, IInteraction est une classe abstraite qui est dérivée beaucoup de fois. Du coup, je dois réécrire la fonction Create dans chacune des classes filles, ce qui n'est pas très propre au point de vue programmation: avant, le code dans le constructeur d'IInteraction était obligatoirement appelé dans les constructeurs des classes filles et les modification du code dans le constructeur d'IInteraction y étaient répercutées aussi. Maintenant ce n'est plus le cas puisque le code n'est plus dans le constructeur

    Est ce quelqu'un a une idée pour résoudre ce problème???
    Merci!!!

  4. #4
    Membre expérimenté Avatar de Nogane
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    241
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 241
    Par défaut
    Si j'ai bien compris, le problème est de copier/coller le code de Create dans toute les class filles?
    Une solution serais de faire de Create une fonction libre, et template:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    template<typename I>
    boost::shared_ptr<I> CreateInteraction(boost::weak_ptr<CPointMechanicsEngine> iEngine)
    {
      boost::shared_ptr<I> newPtr(new I(iEngine));
      boost::shared_ptr<CPointMechanicsEngine> Engine(iEngine);
      Engine->AddInteraction(newPtr);
      return newPtr;
    }
     
    class IInteraction : public enable_shared_from_this<IInteraction>
    {
      template<typename I>
      friend boost::shared_ptr<I> CreateInteraction(boost::weak_ptr<CPointMechanicsEngine> iEngine);
     
    protected:
      IInteraction( boost::weak_ptr<CPointMechanicsEngine> iEngine ) :
        _Engine( iEngine )
      {
      }
     
      boost::weak_ptr<CPointMechanicsEngine> _Engine;
    };
    Il va de soit que, mis a par l'appel a Engine->AddInteraction, le code de construction des class reste bien dans leurs constructeurs respectifs.

    EDIT:
    Après réflexion, vos class d'Interaction n'auront peut-etre pas les même constructeurs.
    Une autre solution pourrait être de laisser CPointMechanicsEngine::AddInteraction faire tout le travaille:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    struct CPointMechanicsEngine
    {
      boost::shared_ptr<IInteraction> AddInteraction(IInteraction *interPtr)
      {
        boost::shared_ptr<IInteraction> sharedInter(interPtr);
        sharedInter->setParent(shared_from_this());
        //Ajout de l'IInteraction dans l'Engine
        //...
        return sharedInter;
      }
    };
     
    //Utilisation:
    shared_ptr<IInteraction> interPtr = Engine->AddInteraction(new InteractionSpecifique(x, y, z));

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    27
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 27
    Par défaut
    Ce qui serait bien, c'est que:
    - une fois la fonction pour créer mon interaction terminée, il n'y ait plus rien à faire pour qu'elle soit utilisable (RAII)
    - que les classes qui dérive de IInteraction soit obligées de faire comme il faut (s'attacher au moteur, etc). Avant, elles devaient appeller le constructeur de IInteraction, qui faisait ce qu'il fallait, et du coup elles faisaient ce qu'il fallait. Maintenant, elles ne sont plus obligées de faire ce qu'il faut.

    Effectivement, les constructeurs de mes interactions sont différents les un des autres.

    La dernière méthode proposée est bien mais pas parfaite car l'utilisateur peut faire un new InteractionSpecifique(x, y, z) quelque part dans le code, sans Engine->AddInteraction, et la RAII ne se ferait pas

    C'est frustrant, il n'y aurait pas de problèmes si j'utilisais des pointeurs basiques

  6. #6
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Pas si le constructeur est privé, et la fonction de création amie de la classe.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

Discussions similaires

  1. utiliser shared_from_this dans le destructeur
    Par nonozor dans le forum Boost
    Réponses: 8
    Dernier message: 12/07/2010, 09h11
  2. Utilisation d'un membre static dans le constructeur
    Par samitriani dans le forum C++
    Réponses: 3
    Dernier message: 10/03/2008, 18h12
  3. Réponses: 5
    Dernier message: 12/03/2006, 14h38
  4. Utilisation de MAX dans une requête SQL
    Par Evil onE dans le forum Langage SQL
    Réponses: 7
    Dernier message: 15/06/2004, 18h38
  5. Utilisation de Pointeurs dans API windows
    Par Drooxy dans le forum API, COM et SDKs
    Réponses: 4
    Dernier message: 13/03/2003, 22h39

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo