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

  1. #1
    Nouveau membre du Club
    Acces à une meth avec un it d'un conteneur de ptr sur objet
    Bonjour la comunauté,

    DSL pour le style télégraphique du titre, je n'ai pas trouvé plus explicite...

    J'ai un vector qui contient des pointeurs std::unique_ptr pointant sur des objets de la classe Fenetre :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    std::vector <std::unique_ptr<Fenetre> > vPfenetre


    Je voudrais accéder à la methode getType() de la classe Fenetre qui me renvoie un typeFenetre (enum class Public déclaré dans la classe Fenetre)

    Si je code comme suit :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    for(unsigned int i(0); i < m_vPfenetre.size(); ++i)
                {
                    if(vPfenetre[i] -> getType() == Fenetre::typeFenetre::fCarte)
                    {
                        // fait des trucs
                        i = vPfenetre.size();
                    }
                }

    ça compile et fonctionne comme espéré.

    mais si je code avec un itérator comme suit :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
       for(auto it = vPfenetre.begin(); it != vPfenetre.end(); ++it)
                {
                    if (*it -> getType() == Fenetre::typeFenetre::fCarte) // it ou *it renvoie le même message d'erreur
                    {
                    // fait des trucs
                    it = vPfenetre.end();
                    }
                }

    Le compilateur me dit :
    error: 'class std::unique_ptr<Fenetre>' has no member named 'getType'

    Je ne comprends pas : *it ne déréférence t-il pas le pointeur itéré de vPfenetre qui accéde à la méthode getType() de la classe Fenetre via l'opérateur -> comme vPfenetre[i] dans le premier cas ?
    J'ai potentiellement quelques cas similaires et j'aimerais bien comprendre l'utilisation des itérators avant de travailler ces autres cas.

    Rick.

  2. #2
    Membre expert
    -> est prioritaire sur *, il faut ajouter des parenthèses: (*it)->getType().

  3. #3
    Expert confirmé
    Bonjour,

    Et attention à ta ligne 6. si tu mets end() dans it, le ++it qui suit te fait aller au dela de end() qui n'a aucun sens! Un simple break est largement préférable!
    Il y a plus simple pour parcourir une collection :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
                for ( auto&& pfen : vPfenetre )
                {
                    if ( pfen->getType() == Fenetre::typeFenetre::fCarte )
                    {
                    // fait des trucs
                    break;
                    }
                }

  4. #4
    Nouveau membre du Club
    Ha ha c'était aussi simple que ça !

    DSL du dérangement mais la syntaxe du c++ est tellement pointue que je n'ai pas encore les bons réflexes de contrôle (comme vérifier systématiquement les règles de priorité par ex...)
    @Dalfab : Noté, merci du tuyau. (les && ne sont pas encore de ma compétence de faux débutant, mais le break oui ! ^^)

    Sujet clos.
    Rick.

  5. #5
    Expert éminent sénior
    Salut,

    Ceci étant dit, tout indique dans ta question que ta classe Fenetre sert de classe à toute une hiérarchie qui va bien au delà de la seule classe dont le type est représenté par fCarte, et, par conséquent, que tu utilise la fonction getType pour assurer une certaine forme de RTTI (Run Time Type Information).

    Je ne serais, du coup, pas plus étonné que cela si la partie de ton code que tu as désignée à l'aide du commentaire // fait des trucs commençait par un code proche de
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    FenetreCarte * temp = static_cast<FenetreCarte *>( (it*)get() );
    ou quelque chose de très similaire (le nom de la classe peut changer, tu utilises peut-être dynamic_cast, ou pire, un cast barbare "à la C" ).

    Et je ne serais pas étonné outre mesure si ton code se poursuivait avec une série de else if ( pfen->getType() == une valeur différente) dont tous les cas seraient basés sur une logique sommes toutes similaires.

    Ce genre de pratique est une véritable catastrophe!!! parce qu'elle va totalement à l'encontre du deuxième principe SOLID : le O, pour OCP, qui est l'acronype de Open Closed Principle (ou si tu préfère en francais, le "principe Ouvert / Fermé"), qui nous rappelle qu'un code doit être "ouvert aux évolutions", mais "fermé aux modifications".

    Pour t'aider à la compréhension de ce principe, disons simplement que, tu as écrit ton code, qu'il compile, et que tu as pu déterminer qu'il fait exactement ce qu'il est sensé faire, tu n'as plus la moindre raison d'aller le modifier : l'ajout d'une évolution ou d'une nouvelle fonctionnalité doit pouvoir se faire sans toucher à la moindre ligne du code existant.

    La logique que je subodore au travers du peu de code que tu donnes me laisse à penser -- même si je peux me tromper, ce dont je doute -- me laisse à penser que, si tu voulais ajouter un nouveau type de fenêtre demain, tu serais obligé d'aller modifier cette succession de if ... else if pour pouvoir prendre le nouveau type de fenêtre en compte.

    Pire encore : je suis quasiment sur que, au fil du temps, tu vas te retrouver avec des dizaines de places dans ton code où ce genre de logique sera mise en œuvre. Et c'est bien là que se trouve tout le problème, car cela signifie que tu devras modifier ton code à des dizaines d'endroits pour pouvoir prendre le nouveau type de fenêtre en compte.

    Or, au fil du temps, tu vas forcément oublier la plupart de ces endroits dans ton code, pour la simple et bonne raison que tu sera concentré sur "autre chose". Et le résultat ne se fera pas attendre : il y aura systématiquement "toute une série" de situations dans lesquelles ... ton nouveau type de fenêtre ne sera pas pris en compte; c'est à dire autant de situations dans lesquelles tu sera face à un bug

    Pour éviter ce genre de problème, le concept clé est double dispatch, dont l'une des mises en oeuvre classique (bien que n'étant pas forcément la plus efficace dans toutes les situations) est représentée par le patron de conception Visiteur.

    Je ne peux que te recommander avec la plus grande vigueur de t'intéresser au plus vite à ce concept et à sa mise en oeuvre
    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

###raw>template_hook.ano_emploi###