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

Affichage des résultats du sondage: "Toute (re)définition de fonction virtuelle doit être finale"

Votants
14. Vous ne pouvez pas participer à ce sondage.
  • C'est une très bonne règle qu'il conviendra de respecter

    0 0%
  • Il est bien de chercher à s'y tenir, mais en pratique c'est trop restrictif

    10 71,43%
  • C'est totalement innapplicable et ça n'apporte rien.

    4 28,57%
C++ Discussion :

[Qualité] Une fonction membre virtuelle définie doit être finale


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 296
    Par défaut [Qualité] Une fonction membre virtuelle définie doit être finale
    Bonjour,

    Je suis en train d'évaluer/analyser un outil d'analyse statique de code, dans sa dernière version, il y a une nouvelle vérification d'une règle MISRA C++ qui en substance exige que toute fonction virtuelle définie ne doive jamais être re-définie -- à quelques exceptions près pour les destructeurs et pour les fonctions virtuelles pures qui ont des implémentations par défaut.

    Je gamberge depuis deux jours sur le sujet, et j'ai du mal à me faire une idée entre:
    - ça n'apporte pas grand chose
    - ça introduit des complications qui vont nous brider
    - c'est un vrai gros plus.

    Dans tous les cas, je n'ai pas trouvé d'exemples qui allaient vraiment dans un sens ou dans l'autre.

    En gros, cela nous interdit les classiques
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    struct Child : Super {
        virtual void f() {
            foo()
            Super::f();
            bar();
        }
    };
    et ce n'est pas un mal. Bien au contraire -- oui, je préfère le DP Template Method.

    Mais cela complique aussi les choses pour définir des comportements par défaut qui pourraient être spécialisés dans des classes filles. Ce qui interdirait ce genre de chose (que j'utilise dans mes cours)
    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
    26
    struct DataRenderer : noncopyable{
        virtual ~DataRenderer() {}
        void render(DataList const& dataList_) {
            do_prologue();
            for (auto const& data : dataList_) { do_render(data); }
            do_epilogue();
       }
    private:
       virtual void do_prologue() {} // oui il y a une implémentation par défaut qui n'en fout pas une
       virtual void do_epilogue() {} // oui il y a une implémentation par défaut qui n'en fout pas une
       virtual void render(Data const& data_) = 0;
    }
     
    struct XMLDataRenderer : DataRenderer {
    private:
       virtual void do_prologue() override { cout << "<datalist>"; } // je viole la règle
       virtual void do_epilogue() override { cout << "</datalist>";} // je viole la règle
       virtual void render(Data const& data_) override { ... }
    };
     
    struct GnuplotDataRenderer : DataRenderer {
    private:
       // ici, je profite de l'implémentation par défaut du prologue et de l'épiloque
       // et il en ira de même pour des sorties .csv/.tsv/...
       virtual void render(Data const& data_) override { ... }
    };
    Est-ce vraiment hérétique d'être pragmatique en profitant de ce comportement par défaut ?
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  2. #2
    Membre Expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Par défaut
    Hello

    Citation Envoyé par Luc Hermitte Voir le message
    Est-ce vraiment hérétique d'être pragmatique en profitant de ce comportement par défaut ?
    Pour ma part, à ceci je répond non. Le comportement par défaut est particulièrement utile pour écrire des adapters.

  3. #3
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Cela ressemble beaucoup à "Seules les classes feuilles de la hiérarchie peuvent être concrètes".
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  4. #4
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 296
    Par défaut
    @Medinoc, cela adresse d'autres aspects orthogonaux.
    Le fait que ma classe de base est abstraite est un détail : il pourrait y avoir une autre classe dérivée qui spécialise un comportement, mais qui reste abstraite.

    Après, il est vrai que ce que tu énonces interdit de redéfinir une fonction qui a déjà été définie.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  5. #5
    Membre Expert
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Par défaut
    Je vais seulement faire une remarque, mais pour l’instant je me garderai bien de porter un jugement définitif.

    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     void render(DataList const& dataList_) {
            do_prologue();
            // corps de fonctnio
            do_epilogue();
       }
    private:
       virtual void do_prologue() {} // oui il y a une implémentation par défaut qui n'en fout pas une
       virtual void do_epilogue() {} // oui il y a une implémentation par défaut qui n'en fout pas une

    et
    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    struct Child : Super {
        virtual void f() {
            foo()
            Super::f();
            bar();
        }
    };

    C’est la même chose, à la différence près que dans le premier cas, on a intégré dès le départ que le corps de la fonction pouvait être précédé d’un prologue / suivi d’un épilogue, alors que dans le deuxième on a fait ça un peu à la rache.

  6. #6
    Membre éprouvé Avatar de KsassPeuk
    Homme Profil pro
    Ingénieur Chercheur
    Inscrit en
    Juillet 2013
    Messages
    138
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur Chercheur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2013
    Messages : 138
    Par défaut
    Lu'!

    Autant si je trouve que le premier cas évoqué est effectivement intéressant, le gain n'est pas assez grand pour justifier qu'on sacrifie le fait d'avoir plusieurs niveaux de variations pour les hiérarchies de classe. Le principal c'est surtout que la fonction membre implémentée respecte le contrat défini par la classe parente (et inductivement si c'est un membre dont elle hérite elle-même).

    Après, quand on utilise le NVI pour vérifier ce genre de contrat, le problème c'est qu'à la première implémentation, on ne peut plus vérifier les contrats de nouvelles variations. Si on veut le faire, ça passe par un nouveau niveau de NVI. Donc on se retrouve dans le cas évoqué ici : une première variation définie est finale.

    Après, j'suis pas un pro moi hein.

Discussions similaires

  1. Réponses: 14
    Dernier message: 16/05/2006, 11h26
  2. Réponses: 3
    Dernier message: 29/04/2006, 13h02
  3. Réponses: 4
    Dernier message: 01/12/2005, 12h33
  4. Réponses: 3
    Dernier message: 28/11/2005, 12h15
  5. Thread avec une fonction membre d'une classe
    Par SteelBox dans le forum Windows
    Réponses: 6
    Dernier message: 01/03/2004, 01h15

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