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

Langage C++ Discussion :

méthode virtuelle pure et implémentation par défaut.


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Invité
    Invité(e)
    Par défaut méthode virtuelle pure et implémentation par défaut.
    Salut,
    Problèmes du jour:
    J'ai une classe abstraite que voilà
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
     
    class A
    {
    	public:
    		virtual void exec()=0 {return;}
    };
    apparament le compilateur ne semble pas apprécier que je définisse la méthode exec dans la déclaration de la classe.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    13 C:\Documents and Settings\Utilisateur\Bureau\test2.cpp pure-specifier on function-definition
    Dans mon cours de langage, la définition pouvait se faire à l'intérieur de la classe. Cela atil changé??

    Qu'à cela ne tienne, tentons de la définir en dehors.
    J'ai mainetenant un système de classes que voila:

    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
    27
    28
    29
    30
    31
    32
    33
    34
    35
     
    class A
    {
    	public:
    		virtual void exec()=0;
    };
     
    void A::exec()
    {
    	return;
    }
     
     
     
     
     
    class B
    {
    	public:
    		void exec(){cout << "blabla" << endl;}
    };
     
     
    class C: public A, public B
    {
    	public :
    		using B::exec;
    };
     
     
    int main()
    {
    	C c;
    	c.exec();
    }
    Ici, le compilo cale à la déclaration de "c" dans le main. car soidisant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    43 C:\Documents and Settings\Utilisateur\Bureau\test2.cpp cannot declare variable `c' to be of type `C' 
    43 C:\Documents and Settings\Utilisateur\Bureau\test2.cpp   because the following virtual functions are abstract: 
    17 C:\Documents and Settings\Utilisateur\Bureau\test2.cpp  virtual void A::exec()
    Je pensais qu'on pouvait définir un comportement par défaut aux méthodes virtuelles pures que s'il n'est pas redéfini par une classe fille, ce sera le comportement adopté par cette dernière.

    Ou bien ça a changé??
    Ou bien jai foiré quelque part dans mon code??

  2. #2
    Membre Expert

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Par défaut
    Bonjour,
    Citation Envoyé par thenano
    Je pensais qu'on pouvait définir un comportement par défaut aux méthodes virtuelles pures que s'il n'est pas redéfini par une classe fille, ce sera le comportement adopté par cette dernière.
    Edit : Oups, je m'ai trompé.
    Effectivement d'après la faq c'est possible...
    Qu'est-ce qu'une fonction virtuelle pure ?
    Qu'est-ce qu'une classe abstraite ?

  3. #3
    Membre éclairé
    Profil pro
    System Integration Project Manager
    Inscrit en
    Octobre 2006
    Messages
    219
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : System Integration Project Manager
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2006
    Messages : 219
    Par défaut
    Salut,
    Citation Envoyé par thenano Voir le message
    Je pensais qu'on pouvait définir un comportement par défaut aux méthodes virtuelles pures que s'il n'est pas redéfini par une classe fille, ce sera le comportement adopté par cette dernière.

    Ou bien ça a changé??
    Ou bien jai foiré quelque part dans mon code??
    t'as loupé un chapitre peut etre

    Une methode virtuelle pure n'a pas de comportement par defaut. C'est aux classes derivees de le definir car sinon tu ne pourras meme pas instancier un objet de cette classe.

    Si tu veux avoir une methode avec un comportement par defaut, alors il te faut coder ce comportement et utiliser le mot clé virtual comme tu l'as fait mais il faut virer le =0.

    V

  4. #4
    Membre émérite
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    865
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 865
    Par défaut
    Citation Envoyé par thenano
    Dans mon cours de langage, la définition pouvait se faire à l'intérieur de la classe. Cela atil changé??
    La norme dit le contraire.
    a function declaration cannot provide both a pure-specifier and a definition
    Est-ce que ton cours précise quel compilo est utilisé ? C'est peut-être une liberté donnée par un compilo mais ce comportement ne respecte pas la norme.

    Citation Envoyé par vdaanen
    Une methode virtuelle pure n'a pas de comportement par defaut.
    Si, justement c'est possible. Voir la FAQ http://cpp.developpez.com/faq/cpp/?p...ction_vituelle

  5. #5
    Membre éclairé
    Profil pro
    System Integration Project Manager
    Inscrit en
    Octobre 2006
    Messages
    219
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : System Integration Project Manager
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2006
    Messages : 219
    Par défaut
    Citation Envoyé par aoyou Voir le message
    Si, justement c'est possible. Voir la FAQ http://cpp.developpez.com/faq/cpp/?p...ction_vituelle
    mea culpa !
    mais je ne vois pas l'intérêt d'avoir un comportement pas défaut sur une méthode virtuelle pure puisque cette dernière doit être reimplementée...
    c'est pas clair je trouve cette histoire...

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par vdaanen Voir le message
    mea culpa !
    mais je ne vois pas l'intérêt d'avoir un comportement pas défaut sur une méthode virtuelle pure puisque cette dernière doit être reimplementée...
    c'est pas clair je trouve cette histoire...
    L'intérêt, c'est que tu peux tout à fait donner comme comportement par défaut qu'il te suffira d'invoquer explicitement sans devoir le copier dans toutes les classes filles qui s'en contentent.

    Plutôt que d'avoir un code proche de
    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
    27
    28
    29
    30
    class Mere
    {
        public:
            virtual void foo() =0; // non implémenté, donc à réimplémenter dans
                                         // toutes les classes dérivées
    };
    class Fille1: public Mere
    {
        public:
            virtual void foo();
    };
    class Fille2: public Mere
    {
        public:
            virtual void foo();
    };
    void Fille1::foo()
    {
        /* une logique potentiellement imposante qui pourrait servir de
         *  comportement par défaut
         * et s'étendant éventuellement sur de nombreuses instructions / 
         * tests / boucles
         */
    }
    void Fille2::foo()
    {
        /* exactement le même comportement que dans Fille1
         * (ce qui entraine une duplication du code, qui n'est jamais souhaitable)
         */
    }
    tu aurais un code proche de
    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
    27
    28
    29
    30
    31
    32
    33
    class Mere
    {
        public:
            virtual void foo() =0; 
    };
    class Fille1: public Mere
    {
        public:
            virtual void foo();
    };
    class Fille2: public Mere
    {
        public:
            virtual void foo();
    };
    void Mere::foo()
    {
        /* une logique potentiellement imposante qui sert de
         *  comportement par défaut
         * et s'étendant éventuellement sur de nombreuses instructions / 
         * tests / boucles
         */
    }
    void Fille1::foo()
    {
        /* Fille1 se contente du comportement par défaut */
        Mere::foo();
    }
    void Fille2::foo()
    {
        /* et Fille2 aussi */
        Mere::foo();
    }
    Le fait qu'une duplication de code n'est jamais souhaitable se rapporte aux deux axiomes suivants:
    • Axiome : Plus le nombre de lignes de codes est élevé, plus il y aura de bugs dedans, et plus la probabilité d'en oublier un est élevée.
    • Axiome : Tout code inutile (code mort et/ou redondant, ce qui n'inclus pas le code de conservation d'intégrité bien sûr) est une source de bugs et/ou de perte de performances, et doit donc être supprimé.
    (citation tronquée d'une intervention de Mac LAK d'aujourd'hui )

    et t'assure que, si un jour, tu en viens à vouloir modifier le comportement par défaut (ne serait-ce que parce que tu t'es rendu compte à l'usage que le comportement par défaut existant représente en réalité une exception), tu n'aura qu'à le modifier à un seul et unique endroit pour observer que toutes les classes dérivées qui utilisent ce comportement par défaut suivent le mouvement
    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

  7. #7
    Membre éclairé
    Profil pro
    System Integration Project Manager
    Inscrit en
    Octobre 2006
    Messages
    219
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : System Integration Project Manager
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2006
    Messages : 219
    Par défaut
    merci de tes explications .. je n'avais jamais vu la chose sous cet angle ...
    V

  8. #8
    Membre Expert
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
     
     
    class C: public A, public B
    {
    	public :
    		void exec() { B::exec(); }
    };

  9. #9
    Membre Expert

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Par défaut
    Citation Envoyé par Goten Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    class C: public A, public B
    {
    	public :
    		void exec() { B::exec(); }
    };
    Boudiou, ça marche en effet !
    Goten, explique !

  10. #10
    Membre Expert
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Par défaut
    Qu'est ce qui te paraît pas clair dans le fait que ça marche? Car bizarrement moi ça me parle, je trouve ça naturel... (peut être signe d'incompréhension partielle d'ailleurs).

  11. #11
    Invité
    Invité(e)
    Par défaut
    Merci pour toutes vos réactions
    Citation Envoyé par Goten Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    class C: public A, public B
    {
    	public :
    		void exec() { B::exec(); }
    };
    En effet cette solution fonctionne, et c'est normal.

    Ce que je n'avais pas compris c'est que le fait de proposer une implémentation par défaut pour une méthode virtuelle pure ne dispense pas la classe fille de redéfinir cette méthode en appelant l'implémentation par défaut de la classe abstraite.

    Dans mon cas cela ne sert à rien, puisque je veux appeler la méthode exec de B et pas de A. (et je voulais faire ça par un using, et non pas en utilisant la solution de Goten) // juste pour voir si c'était faisable.
    Pour cela oui, il faudrait rendre A::exec virtuelle "impure" càd sans =0.

    jai tout compris
    Merci

  12. #12
    Membre Expert

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Par défaut
    cannot declare variable `c' to be of type `C'
    because the following virtual functions are abstract:
    virtual void A::exec()
    En fait, ce problème n'est pas lié à la définition par défaut de exec dans A. Il manque une fonction virtuelle exec dans la classe C qui redéfinirait la fonction virtuelle exec de A. C possède certes une fonction exec() hérité de B, mais C ne remplit quand même pas son contrat avec A.

    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
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
     
    class A
    {
       public:
          virtual void exec()=0;
    };
     
    void A::exec()
    {
       return;
    }
     
    class B
    {
       public:
          void exec(){std::cout << "exec B" << std::endl;}
    };
     
     
    class C: public A, public B
    {
       public :
          virtual void exec();
             using B::exec;
    };
     
    void C::exec()
    {
        std::cout << "exec A" << std::endl;
    }
     
     
    int main()
    {
        C c;
        c.exec(); // affiche exec A
        c.B::exec(); // affiche exec B
    }

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 13
    Dernier message: 10/01/2013, 15h19
  2. Réponses: 5
    Dernier message: 14/10/2012, 19h25
  3. Réponses: 1
    Dernier message: 02/03/2007, 10h37
  4. Problème avec une méthode virtuelle pure
    Par Burckel dans le forum C++
    Réponses: 4
    Dernier message: 05/12/2006, 13h00
  5. implémentation par défaut
    Par BigNic dans le forum C++
    Réponses: 2
    Dernier message: 22/03/2006, 09h21

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