• # Appels surchargés

    Posté par  . Évalué à 3.

    De manière générale pour appeler une méthode de la classe parente tu fais:

    ClasseParente::methode(paramètres);

    donc ici tu écris :

    template<class T>
    class MonVecteur : std::vector<T*>{

    MonVecteur < T >& MonVecteur::operator=(const MonVecteur< T >& other){
    std::vector<T*>::operator=(other);
    //traitement
    .
    .
    .
    //fin traitement
    return *this;
    }

    };

    note : éviter l'héritage public est necessaire si tu veux garder la cohérence objet et éviter qu'un programmeur fasse appel à push_back() (ou autre méthode) qui n'a rien à voir avec ta nouvelle classe...
    • [^] # Re: Appels surchargés

      Posté par  . Évalué à 1.

      Il manque la protection contre l'auto-assignement:
      template<typename T>
      vecteur< T >& vecteur< T >::operator=( const vecteur< T >& rhs )
      {
       if ( this != &rhs ) {
         std::vector<T*>::operator=(rhs);
         //... do stuff
       }
       return *this;
      }
      
      mais c'est juste pour pinailler. :)
      • [^] # Re: Appels surchargés

        Posté par  (site web personnel) . Évalué à 2.

        Non.
        Ceci est un contre idiome qui se résume à une pessimisation.

        http://c.developpez.com/faq/cpp/?page=surcharge#DIVERS_auto_(...)

        http://www.gotw.ca/gotw/059.htm
        • [^] # Re: Appels surchargés

          Posté par  . Évalué à 1.

          Ok, c'est sous-optimal dans la plupart des cas.
          Mais :
          - c'est du KISS (Keep it simple stupid).
          - il sera toujours temps d'optimiser, apres.
          - dans le cas present, il me semble que ce n'est pas judicieux puisque cela fait intervenir un std::vector temporaire plus sa copie. Tout bon compilo devrait pouvoir optimiser cela (je suppose), mais...

          De toute facon, saimal d'heriter des conteneurs de la STL.
          • [^] # Re: Appels surchargés

            Posté par  . Évalué à 1.

            et pourquoi saimal ? pas pratique on le savait, puisque les methodes ne sont pas virtuelles, à commencer à les destructeurs, mais à part ça ...
            • [^] # Re: Appels surchargés

              Posté par  . Évalué à 1.

              puisque les methodes ne sont pas virtuelles, à commencer [par] les destructeurs
              Ben voila, t'as la reponse :)

              Puisque tu ne peux/dois pas surcharger les methodes du conteneur, et que son destructeur n'est pas virtuel, ca fait 2 bonnes raisons pour avoir une classe qui soit implementee par aggregation/composition plutot que par heritage.
              • [^] # Re: Appels surchargés

                Posté par  (site web personnel) . Évalué à 1.

                Cela va même plus loin que cela. Il ne s'agit que de la partie syntaxico-visible de l'iceberg.

                La question qu'il faut se poser est : "est-ce que les objets de la nouvelle classes seront des représentants de la classe ancêtre" <=> "peut-on substituer des objets fils là où l'on attend des objets du type parent?"

                Bien souvent, on va se rendre compte que non -- dans le cas des conteneurs.
                - s'il s'agit de rajouter des services, on peut les rajouter à côté. Ils feront toujours parti de l'interface publique, étendue de l'objet.
                - Il est parfois acceptable (!= ultimement propre, ...) de dériver pour les rajouter tant qu'il n'y a pas de nouvelle donnée membre (pour éviter d'éventuels slicings), et que l'on ne joue pas à détruire polymorphiquement.
                - s'il s'agit de modifier des services, ben ...on casse vite les contrats établis par le parent. L'exemple typique, c'est la définition d'une liste triée à partir d'un liste. Exemple typique où l'héritage (public en C++, quelconque en Java) n'est pas acceptable. Ici, on ne veut pas "être utilisé en place de" , on veut "réutiliser" => héritage privé ou délégation queconque
                - s'il s'agit de spécialiser le conteneur pour des objets précis pour lesquels on veut un traitement suplémentaire bien précis, de nouveau, on bride le contrat initial. On veut réutiliser du code, pas être utilisés en place de.

                Ici le polymorphisme d'inclusion (impliqué par l'héritage public) est rarement la solution si on veut factoriser le code. Au contraire du polymorphisme paramétrique et statique des templates du C++.
          • [^] # Re: Appels surchargés

            Posté par  (site web personnel) . Évalué à 1.

              Tu n'es pas alllé voir mes liens ? Avoue. :P L'aspect de pessimisation n'est qu'un détail qui n'a pas la moindre importante.
              Le problème est qu'il s'agit d'un contre-idiome qui résoud un problème théorique qui ne se produit jamais, et qui ne résoud pas un problème pratique qui se produit dans des cas aux limites liés à l'exécution. (!= code zarbi)
              Ce hack des années 80-90 n'est pas exception-safe. Alors qu'une solution qui est exception-safe résoud implicitement le problème d'auto-affectation. Hack qui n'est dû qu'aux codes qui préféraient désaouller avant de réallouer, ce qui empéchait d'avoir des opérations atomiques.
              Faire le test ne correspond alors plus qu'à une vaine tentative d'optimisation qui se résoud systématiquement en pessimisation -- sauf code pour le moins étrange.
              Et difficile de faire plus kiss que l'idiome de la copie par swap -- qui s'avère parfois lourd sur les objets ne se résumant à un pointeur encapsulé. Sachant qu'en plus il n'y a strictement aucun intérêt à définir les deux opérations de recopie pour les classes dont tous les membres ont déjà une sémantique de copie -- i.e. pas de ressource brute -- ce qui est encore bien plus dans la philo "kiss".
            struct SmthgCopiable {
                SmthgCopiable ( SmthgCopiable const& rhs ) : ... {...}
                SmthgCopiable & operator=( SmthgCopiable const& rhs) {
                    SmthgCopiable temp(rhs);
                    this->swap(rhs);
                    return this;
                }
                void swap(SmthgCopiable & other);
            };
            • [^] # Re: Appels surchargés

              Posté par  (site web personnel) . Évalué à 1.

              s/swap(rhs)/swap(other)/ Bien évidemment.
            • [^] # Re: Appels surchargés

              Posté par  . Évalué à 1.

              Tu n'es pas alllé voir mes liens ? Avoue. :P

              Si-si, mais je prefere celui-la :)
              http://www.parashift.com/c++-faq-lite/assignment-operators.h(...)

              Par contre, j'etais en effet passe un peu (trop) vite sur les aspects d'exception-safety...
              Garantir la condition de base (pour avoir du code exception-safe), c'est toujours bon a prendre.

              Je vais essayer de m'astreindre a suivre cette implementation dans l'avenir.

              PS: je viens de relire mon "Effective C++" de S.Meyers (3eme Ed.): il laggue un peu :)

              PPS: et je suppose que tu veux dire:
              s/swap(rhs)/swap(temp)/
              • [^] # Re: Appels surchargés

                Posté par  (site web personnel) . Évalué à 1.

                La FAQ C++ lite est effectivement l'original -- où ils passent très vite sur le sujet. Cela fait trop alinéa. :(

                C'est plus clair dans XP++/GOTW et le coding standards de H.Sutter & A.Alexandrescu.

                Pour le PS: je n'ai pas encore investi dans la 3ed du EC++. Qu'entends-tu pas "lagguer" ?

                Pour le PPS: pfff en effet. :-/
                • [^] # Re: Appels surchargés

                  Posté par  . Évalué à 0.

                  Pour le PS: je n'ai pas encore investi dans la 3ed du EC++. Qu'entends-tu pas "lagguer" ?
                  Nan... rien...
                  Je suis le capitaine bigleux.
                  Tout petit deja, j'avais ce probleme...

                  Tout ca pour dire, que, oui, dans son Item 11, S. Meyers recommande en effet d'utiliser la methode decrite plus haut pour gerer l'auto-assignement.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.