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

C++ Discussion :

héritage et chaine d'objets


Sujet :

C++

  1. #1
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2014
    Messages
    521
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2014
    Messages : 521
    Points : 136
    Points
    136
    Par défaut héritage et chaine d'objets
    Bonjour.

    Il se passe quelque chose d'étrange dans mon code...J'aimerais utiliser une chaîne d'objets hérités, qui pourrait être accessible pour chacun d'entre eux.
    Je crée donc une class Container qui jouera le rôle d'un vector amélioré, en somme, en y mettant à l'intérieur un vector d'OBJECT.
    Quand je crée un vector d'OBJECT normale, ca marche.
    quand je crée un vector de std::shared_ptr d'OBJECT, ca plante.

    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
    23
    24
     
     
    class Container_OBJECT
    {
     
    public :
     
        Container_OBJECT() ;
        ~Container_OBJECT() ;
     
        void                                                            setSystem ( std::shared_ptr < System > system ) { _system = system ; }
        void                                                            add ( std::shared_ptr < OBJECT > object ) ;
     
        void                                                            update() ;
        void                                                            destroyed() ;
     
     
    private :
     
        std::shared_ptr < System >                                              _system ;
        std::vector < std::shared_ptr < OBJECT > >                      _OBJECT ;
        OBJECT                                                                            _OBJECT_Test ; //celui ci fonctionne.
     
    };
    exemple d'utilisation :

    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
     
     
    ENGINE::ENGINE()
    {
        ...
     
        std::shared_ptr < Container_OBJECT > modelC ( new Container_OBJECT ) ;
        modelC -> setSystem ( _system ) ;
     
        _Container_OBJECT = modelC ;
     
    }
     
    void ENGINE::load()
    {
            ...
     
            _Container_OBJECT -> destroyed() ;
     
            _Container_OBJECT -> add ( _RESOURCES.getOBJECT( word ) ;
     
    }
    ca plante, et en débug on m'indique l'endroit du bug, dans stl_vector.h :

    { return const_iterator(this->_M_impl._M_finish); }
    En revanche, si je fais la même chose avec l'objet test, qui n'est pas en std::shared_ptr, ca fonctionne.
    Vu que je préfère éviter les pointeurs nu dans ce cas, même si c'est tout de même faisable vu le Container n'est pas censé disparaître, je viens vers vous en espérant avoir peut être une piste/solution/mise en avant d'erreur etc.. et vous poser cette question :

    Cela peut-il être lié au fait que mon "OBJECT" soit dérivé en d'autres objets ?

    Merci si vous pouvez m'aider.

  2. #2
    Membre éclairé

    Profil pro
    Inscrit en
    Décembre 2013
    Messages
    393
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2013
    Messages : 393
    Points : 685
    Points
    685
    Par défaut
    Si les messages d'erreur font plusieurs lignes, ce n'est pas pour rien, évites de donner qu'une partie.
    En général, l'erreur n'est pas dans le code de la STL, mais dans le code appelant. Comme tu ne donnes pas le code de destroyed, add, get_OBJECT, on ne va pas pouvoir t'aider.

    Par contre, il n'y a bien sur pas de problème a utiliser les pointeurs intelligents avec le polymorphisme d’héritage.

    HS sur le style :
    - je suppose que tu utilises des tabulations et pas des espaces (d'ou la mise en forme moisi sur le forum). Tu devrais configurer ton IDE pour remplacer automatiquement cela.
    - noms en minuscules et majuscules. Bof (historiquement, les termes tout en majuscules correspond a des macros)
    - évite les noms commençant par _ (c'est pas interdit dans ce cas la, mais cela peut l'etre dans d'autre contexte. L'habitude est de ne pas du tout faire comme cela)
    - préférer make_shared plutot que new
    - pourquoi créer une variable intermédiaire inutile modeleC ?
    - pourquoi _Container_OBJECT est un pointeur ?
    - les pointeurs intelligents permettent de sécuriser le code. Cela ne veut pas dire qu'ils font tout le boulot a la place du développeur. Il faut TOUJOURS tester un pointeur avec de l'utiliser (et plus généralement tester tes pre-conditions)

  3. #3
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Ton code ne montre pas le problème.
    Pourrais-tu faire un "code court compilable" montrant le problème, s'il te plait?
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  4. #4
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Hello,

    Çà ne répond pas vraiment à la question, mais pourquoi autant de std::shared_ptr ?
    Les objets sont tous réellement partagés, ou c'est par simplicité ?

  5. #5
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2014
    Messages
    521
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2014
    Messages : 521
    Points : 136
    Points
    136
    Par défaut
    Merci pour vos réponses et tous les conseils.

    En fait, il ne se passe rien d'autre que ceci, par ex, dans ma fonction destroyed ( qui a elle seul fait planter ) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
     
    void Container_OBJECT::destroyed()
    {
        if ( !_OBJECT.empty() )
        {
     
        }
    }
    une autre "étape" du message d'erreur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
          /**
           *  Returns a read-only (constant) iterator that points one past
           *  the last element in the %vector.  Iteration is done in
           *  ordinary element order.
           */
          const_iterator
          end() const _GLIBCXX_NOEXCEPT
          { return const_iterator(this->_M_impl._M_finish); }
    évite les noms commençant par _ (c'est pas interdit dans ce cas la, mais cela peut l'etre dans d'autre contexte. L'habitude est de ne pas du tout faire comme cela)
    Quelles sont les bonne habitudes à prendre dans ce cas ? Car il s'agit bien d'attributs d'une class. ( je fais jusqu'à présent comme on le dit dans les cours C++, sauf erreur...)

    pourquoi _Container_OBJECT est un pointeur ?
    En fait je suis en train de réaliser que c'est en effet inutile, vu que je pourrais pas l'implémenter dans les objets. Le but étant que chacun y ait accès. Il faudra en revanche qu'ils aient accès à son vector d'objets, pour pouvoir eux même créer d'autres objets quand ils le souhaitent. ( c'est l'objectif du moins ).
    Mais bon, il n’empêche que je ne vois toujours pas pourquoi ça plante...

  6. #6
    Membre éclairé

    Profil pro
    Inscrit en
    Décembre 2013
    Messages
    393
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2013
    Messages : 393
    Points : 685
    Points
    685
    Par défaut
    Citation Envoyé par mazertys17 Voir le message
    une autre "étape" du message d'erreur :
    Tu n'as pas compris quoi quand j'ai dit "évites de donner qu'une partie" ?

  7. #7
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2014
    Messages
    521
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2014
    Messages : 521
    Points : 136
    Points
    136
    Par défaut
    dison que la totalité c'est un peu lourd non ? ( si c'est bien ce que vous demandez ) :

    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
     
     
    Building to ensure sources are up-to-date
    Selecting target: 
    Debug
    Adding source dir: C:\Users\mathieu\Documents\echappatoire\BigBangElement\BigBangElement\
    Adding source dir: C:\Users\mathieu\Documents\echappatoire\BigBangElement\BigBangElement\
    Adding file: C:\Users\mathieu\Documents\echappatoire\BigBangElement\BigBangElement\bin\Debug\Element.exe
    Changing directory to: C:/Users/mathieu/Documents/echappatoire/BigBangElement/BigBangElement/.
    Set variable: PATH=.;C:\lib;C:\lib;C:\Program Files (x86)\CodeBlocks\MinGW\bin;C:\Program Files (x86)\CodeBlocks\MinGW;C:\Program Files (x86)\Intel\iCLS Client;C:\Program Files\Intel\iCLS Client;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\Windows\System32;C:\Windows;C:\Windows\System32\wbem;C:\Windows\System32\WindowsPowerShell\v1.0;C:\Program Files (x86)\Windows Live\Shared;C:\Program Files\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files (x86)\CMake\bin;C:\Program Files\Microsoft SQL Server\110\Tools\Binn
    Starting debugger: C:\Program Files (x86)\CodeBlocks\MINGW\bin\gdb.exe -nx -fullname  -quiet  -args C:/Users/mathieu/Documents/echappatoire/BigBangElement/BigBangElement/bin/Debug/Element.exe
    done
    Registered new type: wxString
    Registered new type: STL String
    Registered new type: STL Vector
    Setting breakpoints
    Debugger name and version: GNU gdb (GDB) 7.5
    Child process PID: 14296
    Program received signal SIGSEGV, Segmentation fault.
    At c:\program files (x86)\codeblocks\mingw\lib\gcc\mingw32\4.7.1\include\c++\bits\stl_vector.h:883
    Et ce que j'ai mis précédemment, c'est de code direct de la stl, là ou le débug m'indique que ca plante.

  8. #8
    Membre éclairé

    Profil pro
    Inscrit en
    Décembre 2013
    Messages
    393
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2013
    Messages : 393
    Points : 685
    Points
    685
    Par défaut
    Des messages d'erreurs un peu "lourd", c'est plusieurs milliers de lignes. Dans ce cas, ok, il faut pas toutes les donner. Mais la, tu as 20 lignes, c'est pas la mort.

    Cela permet au moins de savoir que la pile des erreurs n'est pas complète. Je n'utilises pas trop Code::Block, mais il faut que le debug s’arrête lors de l'erreur et affiche la pile d'appel des fonctions qui ont causer l'erreur

    Il faut la fenêtre d'appel des fonctions

  9. #9
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    La, tu as exclusivement une segfault.

    Ca veut dire que tu utilise un pointeur invalide.

    Il y a deux grandes causes possibles: un pointeur non initialisé, une copie de pointeur vers un bloc déjà libéré.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void Container_OBJECT::destroyed()
    {
        if ( !_OBJECT.empty() )
        {
     
        }
    }
    Cette fonction me semble très suspecte.
    destroyed est un adjectif, on s'attend avec un tel nom à ce que la fonction retourne un booléan disant si oui ou non *this est "destroyed".

    Du coup, je me demande ce que peut être le _OBJECT membre de Container_OBJECT.
    Et aussi pourquoi ne pas l'avoir appelé inner, internal, contained, ou data.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  10. #10
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 965
    Points
    32 965
    Billets dans le blog
    4
    Par défaut
    C'est un segfault à l'exécution...
    Le debugger s'arrête dans la STL, mais ça on s'en moque - on part du fait que la STL fonctionne, et c'est vrai sur les architectures usuelles -, tu remontes la pile d'appel et tu retomberas sur ton code, et l'origine du problème.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  11. #11
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Salut,
    Citation Envoyé par Bousk Voir le message
    C'est un segfault à l'exécution...
    Le debugger s'arrête dans la STL, mais ça on s'en moque - on part du fait que la STL fonctionne, et c'est vrai sur les architectures usuelles -, tu remontes la pile d'appel et tu retomberas sur ton code, et l'origine du problème.
    Ou, plutôt, sur l'endroit de ton code où tu essayes (de toutes évidences, vu qu'il s'agit d'une erreur de segmentation) d'accéder à un pointeur invalide. Il y a beaucoup de chances, étant donné que tu utilises des std::shared_ptr, que ton code contienne un delete appelé sur un pointeur dont la durée de vie est (justement) normalement prise en charge par les std::shared_ptr et que l'endroit indiqué par ton débuggeur soit sans doute assez éloigné de l'endroit de ton code qui pose réellement problème. Mais, a priori, tu ne devrais pas avoir énormément de delete qui trainent dans ton code
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  12. #12
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2014
    Messages
    521
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2014
    Messages : 521
    Points : 136
    Points
    136
    Par défaut
    Merci pour toutes vos réponses.

    Finalement j'ai pris le parti d'utiliser un conteneur de de la chaîne d'objet utilisé par "l'engine", et d'envoyer le vector qui contient les objets en shared_ptr pour qu'ils y aient tous accès :

    mon but étant que chaque objet qui en a la possibilité puisse créer un autre objet directement de lui même en l'ajoutant au vector.
    Cela donne :

    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
    23
    24
    25
     
     
    class Container_OBJECT
    {
     
    public :
     
        Container_OBJECT() ;
        ~Container_OBJECT() ;
     
        void                                                            setSystem ( std::shared_ptr < System > system ) { _system = system ; }
        void                                                            add ( std::shared_ptr < OBJECT > object ) ;
     
        void                                                            initializes() ;
        void                                                            update() ;
        void                                                            destroyed() ;
     
        std::shared_ptr < std::vector < std::shared_ptr < OBJECT > > >  getContainer() { return _container_Object ; }
     
    private :
     
        std::shared_ptr < std::vector < std::shared_ptr < OBJECT > > >  _container_Object ;
        std::shared_ptr < System >                                      _system ;
     
    };
    et voici le constructeur du container ( est-ce bien correct ? )

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
     
    Container_OBJECT::Container_OBJECT()
    {
        std::shared_ptr <  std::vector < std::shared_ptr < OBJECT > > > model ( new std::vector < std::shared_ptr < OBJECT > > ) ;
        _container_Object = model ;
    }

    cela me permettant de faire ceci, par ex :

    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
     
     
    void OBJECT::build( std::string name )
    {
        for ( auto& it : _objectSource )
        {
            if ( it -> getName() == name )
            {
                std::shared_ptr < OBJECT > model ;
                model = it -> clone() ;
                model -> getPhysics().setPosition( _physics.getPosition() ) ;
                model -> initializes() ;
                _container_Object -> push_back ( model ) ;
            }
        }
    }
    sachant que _container_Object est le container utilisé par l'engine, dont la class est montré dessus.

    Cela fonctionne quand je crée un objet, mais si je veux créer une autre objet ensuite, il plante sans autre explication que le fameux message d'erreur, pointant au moment de l'update.
    Chose étonante, si j'envoi mon objet crée, qui peut lui même créer un objet, créer un autre objet, ca marche. Et je peux même reprendre mon objet de départ et lui demander de créer un nouvel objet, qui créera d'autres objets qui en feront d'autres etc...Jusqu'à ce que, parfois, ca plante...

    voila un exemple de mon clone ( car je me dit que cela pourrait bien venir de là...)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    std::shared_ptr < OBJECT >  OBJECT_Ctr_Terminal::clone()
    {
        std::shared_ptr < OBJECT > model ( new OBJECT_Ctr_Terminal ( *this ) ) ;
     
        return model ;
    }
    mais pourquoi autant de std::shared_ptr ?
    disons que j'ai l'intention de faire un jeux type STR. Le but est que chaque objet actif, par ex, puisse interagir avec d'autres. Donc je me suis dit que pour faire cela aisément, il me faut des shared_ptr, et le système d'héritage. Ainsi je peux utiliser une "_target", par ex, qui va prendre la cible et pouvoir "échanger" directement avec...Le objets ayant tous les mêmes entités à la base ( graphics, physics, state, sound ). le tout géré par l'engine pour pouvoir optimiser au mieux au fur à mesure.

    Je sais que je ne donne pas suffise ment d'infos, mais peut être pouvez vous avoir des pistes, ou des choses à dire sur la conception, qui pourraient m'aider.

    ps: pour les maj, j'ai déjà commencé sur ce model, alors ca va être l'exeption qui confirme la règle, mais seul l'objet mère est tout en maj... en tout cas c'est noté pour la prochaine fois. ( merci, donc )

    pps : j'ai du mal avec le make_shared...Si je l'utilise, ca marche pas. ex :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    std::shared_ptr < OBJECT >  OBJECT_Ctr_Terminal::clone()
    {
        std::shared_ptr < OBJECT > model ( new OBJECT_Ctr_Terminal ( *this ) ) ;
     
        std::shared_ptr < OBJECT > test  =  std::make_shared < OBJECT > ( *this ) ;
     
        return test ;//ca ne marche pas comme avec model.
    }

  13. #13
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2014
    Messages
    521
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2014
    Messages : 521
    Points : 136
    Points
    136
    Par défaut
    ok, je crois savoir d'où ça vient :

    quand je crée un nouvel objet, il l'ajoute au vector, alors même qu'ils sont en train d'être updatés : le container ne sait pas qu'il y en a un en plus, alors il continue avec les ittérators sans le prendre en compte...donc plantage.

    C'est pour ca que j'aurais aimé envoyé le container plutôt que le vector, mais c'est impossible dans la mesure ou le container contient l'objet, donc l'objet ne peut contenir le container.

    Je cherche une solution. Si vous avez des idées/conseil , je suis preneur .

    Merci

  14. #14
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2014
    Messages
    521
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2014
    Messages : 521
    Points : 136
    Points
    136
    Par défaut
    dsl, ca tourne un peu au monologue mais j'ai trouvé une solution et j'aimerais vous demander votre avis

    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
     
    void Container_OBJECT::update()
    {
     
        for ( std::vector < std::shared_ptr < OBJECT >> :: iterator it = _container_Object -> begin() ; it != _container_Object -> end() ; it ++  )
        {
            if ( _system -> _create )
            {
                it =  _container_Object -> begin() ;
                _system -> _create = false ;
            }
            if ( !( *it ) -> _updated )
            {
                ( *it ) -> update() ;
            }
        }
        for ( auto& it : *_container_Object )
        {
            it -> _updated = false ;
        }
    }
    dans l'update, si un objet en crée un autre, il le dit au system, en lui mettant son bool _create en true.
    l'itterator est alors remis au début et le _create du system remis en false.
    pour pas qu'il update 2 fois le même objet, il verrifie chaque objet si celui ci a déjà été updaté.
    après avoir fait tous les updates, il remets tous les objets en _updated false...

    donc maintenant ca fonctionne, mais j'ai le sentiment que ca gaspille beaucoup d'énergie...

  15. #15
    Membre éclairé

    Profil pro
    Inscrit en
    Décembre 2013
    Messages
    393
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2013
    Messages : 393
    Points : 685
    Points
    685
    Par défaut
    Cela me semble un peu bancale globalement en termes de conception. Mais ton problème de conteneur mis à jour pendant qu'il est parcouru est assez classique. Une solution simple est de simplement mettre les nouveaux objets dans un conteneur temporaire, et à la fin du traitement du premier conteneur, fusionner les 2 conteneurs (en général, on n'a pas besoin de faire l'update des objets au même tour que leur création).

    Un livre à lire (la version en ligne est gratuite) : http://gameprogrammingpatterns.com (la problématique que tu rencontres est abordées dans le chapitre "game loop" ou "object pool" (je ne sais plus. De toute façon, tout le livre est intéressant à lire)

  16. #16
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Une autre solution peut être de ne pas utiliser d'itérateurs (puisqu'ils peuvent être invalidés)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void Container_OBJECT::update() {
        for (size_t i=0; i<_container_Object->size(); ++i) {
            (*_container_Object)[i]->update();
        }
    }
    Si des objets sont ajoutés / supprimés en début de vecteur (avant l'objet en train d'être traité), certains ne seront pas mis à jour ou mis à jour plusieurs fois.
    Si update ne peut qu'ajouter des objets à la fin du vecteur (push_back / emplace_back), pas de problèmes.

    (Le fait que tu n'arrives pas à justifier correctement l'utilisation de std::shared_ptr indique que tu n'en à très certainement pas besoin. )

  17. #17
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2014
    Messages
    521
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2014
    Messages : 521
    Points : 136
    Points
    136
    Par défaut
    Merci pour les infos et les solutions.

    Le fait que tu n'arrives pas à justifier correctement l'utilisation de std::shared_ptr indique que tu n'en à très certainement pas besoin. )
    Disons que j'ai le sentiment de justifier l'utilisation des std_shared_ptr :

    un exemple: j'ai un objet qui va se balader, et, s'il se trouve proche d'un autre objet, il va falloir qu'il sache si celui ci, par ex, est un ennemi ou un allier, pour interagir avec lui. S'il est ennemi, il va donc l'attaquer, et ainsi lui infliger directement du dégât. quoi de mieux que d'avoir accès à l'objet lui même ? donc un pointeur, et pour s'embêter des ennuis, shared_ptr... Surtout que celui ci peut être la cible de plusieurs objets en même temps.

    Etant donné de plus que j'ai pris le partie, finalement, d'utiliser l'héritage pour les objets, l'utilisation des pointeurs pour les copies devient de plus nécessaire ( enfin me semble-t-il ).

    Cela me semble un peu bancale globalement en termes de conception
    qu'est-ce qui te semble bancale en particulier ?

    ps : j'ai test la solution de ne pas utiliser d'iterator, et ca marche nikel. merci

  18. #18
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2014
    Messages
    521
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2014
    Messages : 521
    Points : 136
    Points
    136
    Par défaut
    J'ai un autre problème auquel je vais devoir trouver une solution.
    Si vous avez des idées/conseils, je vous en remercie par avance .

    Je part du principe que tous les objets jouables du jeux seront hérité d'une classe de base OBJECT. J'ai maintenant une class OBJECT_Terminal, qui sera un bâtiment pouvant créer des objets divers. Mais il doit pouvoir également créer un objet mobiles qui pourra lui même créer d'autres OBJECT_Terminal.

    Je me dis donc qu'il faudra que cet objet mobile soit un OBJECT_Terminal, car s'il est un simple objet, ou un OBJECT_Controlable etc...il ne pourra pas construire de lui même des OBJECT_Terminal ( étant donné qu'il est "include" dans un OBJECT_Terminal ).

    Pour éviter d'obliger les OBJECT_Terminal d'avoir également les caractéristiques de l’objet mobile, totalement inutile pour eux, puisque ce sont des bâtiments qui n'ont pas pour vocation de créer d'autres bâtiments, et sont de base immobiles, je me dit que l'idéal serait de créer un nouvel objet hérité type OBJECT_Worker. Mais si cet objet contient des OBJECT_Terminal, il ne pourra donc pas être construit par des OBJECT_Terminal.

    Ca se mord la queue. Je peux donc allourdir ma class OBJECT_Terminal, et, à coup de conditions, faire en sorte qu'elle puisse également être un "worker", mais ca me paraît guerre propre, et lourd autant en code qu'en perf.(même si c'est pas grand chose ).

    Qu'en pensez vous ?

    Merci si vous pouvez m'aider

  19. #19
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 965
    Points
    32 965
    Billets dans le blog
    4
    Par défaut
    L'utilisation de shared_ptr ici est totalement injustifiée.
    un exemple: j'ai un objet qui va se balader, et, s'il se trouve proche d'un autre objet, il va falloir qu'il sache si celui ci, par ex, est un ennemi ou un allier, pour interagir avec lui. S'il est ennemi, il va donc l'attaquer, et ainsi lui infliger directement du dégât. quoi de mieux que d'avoir accès à l'objet lui même ? donc un pointeur, et pour s'embêter des ennuis, shared_ptr... Surtout que celui ci peut être la cible de plusieurs objets en même temps.
    Vive la duplication des infos, avec un shared_ptr sans raison "parce que pointeur". Tu as déjà une instance de jeu, qui contient toutes les données, toutes les données n'ont pas besoin d'une copie de toutes les autres données...

    La solution d'Iradrille aura beaucoup moins de chances de planter, mais n'est à priori pas exclue d'y parvenir. Ton crash c'est un classique de data race. Vaut mieux utiliser une liste dans ce cas, si l'autre thread ne fait que des push_back. Les éléments d'une liste ne sont pas invalidés lors d'un push_back.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  20. #20
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2014
    Messages
    521
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2014
    Messages : 521
    Points : 136
    Points
    136
    Par défaut
    Finalement, j'ai opté pour la solution de mintho carmo, plus pratique pour pouvoir aussi gérer les littérateurs, chose finalement indispensable. Et c'est pas tellement plus lourd en terme de code.

    Vaut mieux utiliser une liste dans ce cas, si l'autre thread ne fait que des push_back. Les éléments d'une liste ne sont pas invalidés lors d'un push_back.
    Merci pour l'info, je vais voir si ca peu être intéressant. Après j'ai besoin d'utiliser les triturateurs tout le temps, donc un vector est peut être plus adapté...

    Tu as déjà une instance de jeu, qui contient toutes les données, toutes les données n'ont pas besoin d'une copie de toutes les autres données...
    ??

    Les données ne sont pas copiés systématiquement dans leu jeu. Elles sont copiés lorsque c'est nécessaire ( a la création de l'objet, par ex ). Donc quand un objet veut savoir ce qui se passe dans un autre, il va simplement voir à son adresse, d'où les pointeurs. Il peut ainsi avoir, par ex, ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
     
    protected :
     
       std::shared_ptr < OBJECT > _target ;
    et l'utiliser ainsi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
     
    void OBJECT_Healer::folow()
    {
       _physics.setDestination ( _target -> getPhysics().getPosition() ) ;
    }
    ps : finalement, pour mon histoire de worker, j'ai décidé de créer la class bien séparément : _OBJECT_Worker. La construction des terminaux se fait donc par le moteur. Le worker ajoute au system le nom du terminal qu'il doit construire, et l'Engine le construit alors. L'objet construit se bâtit si des workers sont dans sa collision trigger...Il s'active une fois construit et devient alors utilisable. Ca a été un peut plus compliqué à mettre en place, mais je pense que c'est plus propre au final, que de "cafouiller" une class OBJECT_Terminal.

    Merci, pour vos avis et conseils qui me sont d'une grande aide

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 3 123 DernièreDernière

Discussions similaires

  1. Héritage et tableau d'objets
    Par Mindiell dans le forum C++
    Réponses: 17
    Dernier message: 08/01/2009, 07h24
  2. [POO] Decoupage de chaine et objet
    Par bobspike dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 27/06/2008, 15h32
  3. Problème d'héritage css (classe et objet)
    Par Askle dans le forum Mise en page CSS
    Réponses: 2
    Dernier message: 03/06/2007, 20h11
  4. Mal a la tete avec liste chainée d'objet
    Par Raton dans le forum C++
    Réponses: 23
    Dernier message: 03/08/2005, 22h13
  5. [Java] Héritage et flux d'Objet
    Par guejo dans le forum CORBA
    Réponses: 2
    Dernier message: 22/02/2005, 11h14

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