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 :

appel d'une fonction surchargée


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    36
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 36
    Par défaut appel d'une fonction surchargée
    Bonsoir,

    J'ai une question qui peut paraître idiote, peut-on écrire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    class Base
    {
        public :
            virtual void f(){};
    }
     
    class Derived : public Base
    {
        public :
            void f(){ Base::f(); };
    }
    Dis comme çà, c'est un peu inutile. Le but est en fait d'utiliser f() tel que définit dans Base en ajoutant des fonctionnalités pour Derived.

    Merci d'avance.

  2. #2
    Membre très actif
    Homme Profil pro
    En rupture avec la societé
    Inscrit en
    Novembre 2008
    Messages
    144
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : En rupture avec la societé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 144
    Par défaut
    salut

    dans un premier temps tu ne surcharge pas une méthode mais tu la redéfinis
    La surcharge correspond a déclarer et définir plusieurs fonctions ayant le même nom, à condition que les listes de leurs arguments diffèrent

    avec la redéfinition de la méthode dans ta class dérivé, tu masque celle de la class de base.
    l'utilisation de virtual fonctionne dans le cadre du polymorphisme.

    et oui effectivement tu peux appeler la méthode de la class de base dans la méthode redéfini de la class dérivé.

    Rien ne t'empêche non plus d'appelé la méthode de la class de basse malgré la redéfinition.
    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
     
    class Base
    {
        public :
            virtual void f(){};
    }
     
    class Derived : public Base
    {
        public :
            void f(){ Base::f(); };
    }
     
    Derived maClass;
    maClass.Base::f();
    a plus

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    36
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 36
    Par défaut
    C'est vrai, ce n'est qu'une redéfinition. Shame on me !

    Mais avec le code suivant, c'est une surcharge, non ?

    Pour mieux comprendre le but :

    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
     
    class Base
    {
        public :          // en "protected :" ça paraît plus compliqué !
            int i;
     
        public :
            virtual void f(){};
    }
     
    class Derived : public Base
    {
        public :
            void f(const int val);
    }
     
    void Derived::f(const int val)
    {
        Base::f();
        i = val;
    }
    Je peux donc écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Derived maClass;
    Base* instanceDerived = &maClass;
     
    instanceDerived->f(0);

  4. #4
    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
    Salut,
    Citation Envoyé par titibete Voir le message
    C'est vrai, ce n'est qu'une redéfinition. Shame on me !

    Mais avec le code suivant, c'est une surcharge, non ?

    Pour mieux comprendre le but :

    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
     
    class Base
    {
        protected :
            int i;
     
        public :
            virtual void f(){};
    }
     
    class Derived : public Base
    {
        public :
            void f(const int val);
    }
     
    void Derived::f(const int val)
    {
        Base::f();
        i = val;
    }
    Là, tu as, effectivement, une surcharge...

    Mais attention, ce n'est pas une redéfinition, ce qui fait que si tu écrivait purement et simplement
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void Derived::f(const int val)
    {
        f();
        i = val;
    }
    sans avoir redéfini void f() dans ta classe dérivée, cela reviendrait exactement au même (car f() est une fonction qui est tout à fait accessible depuis Derived, vu qu'elle fait partie de l'interface publique de Base )
    par contre,
    Je peux donc écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Derived maClass;
    Base* instanceDerived = &maClass;
     
    instanceDerived->f(0);
    Hééé non...

    La raison est simple: ton pointeur instanceDerived passe pour être... du type Base, et non du type Derived.

    Tu ne peux donc invoquer que les fonctions publiques qui font partie de ... l'interface (publique) de Base.

    Or, en tant que Base, la seule fonction qui soit connue, c'est celle... ne prenant aucun argument

    D'ailleurs, si tu avais essayé de compiler, tu t'en serais aperçu, car il t'aurais "jeté" à coup de "fonction f(int) non déclarée dans Base" (ou message similaire )

    Au final: avec tes classes Base et Derived telles que tu les as présentées, tu en arrive aux situations suivantes:
    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
    int main()
    {
        Derived deriv;
     
        deriv.f(); // appelle Base::f(), car elle n'a pas été redéfinie pour Derived
     
        deriv.f(5); // appelle Derived::f(int)
     
        Base & b=deriv; // ca marche aussi avec les références :D
     
        b.f(); // OK : b passe pour être du type Base
     
        b.f(10); // KO : b passe pour être du type Base qui ne déclare pas
                 // de fonction f(int)
     
        return 0;
    }
    EDIT: Il faut noter que, si une fonction est déclarée virtuelle dans la classe de base et redéfinie dans la classe dérivée sans avoir été déclarée virtuelle, la redéfinition dans la classe dérivée sera néanmoins réputée virtuelle.

    Si tu invoque la fonction redéfinie au départ d'un objet dont le type réel est la classe dérivée mais passant pour être du type de la classe de base, tu observera effectivement le comportement polymorphe, car ce sera bel et bien la version de la classe dérivée qui sera utilisée.

    Par contre, si la fonction n'est pas déclarée virtuelle dans la classe de base, et qu'elle est redéfinie dans la classe dérivée, la redéfinition cachera simplement l'implémentation de la classe de base.

    Cela signifie que, si tu invoque la fonction depuis un objet du type de la classe dérivée, ce sera la version de la classe dérivée qui sera utilisée, mais que si tu invoque la fonction depuis un objet dont le type réel est la classe dérivée mais passant pour être un objet du type de la classe de base (référence ou pointeur), ce sera... la version de la classe de base qui sera utilisée, et tu n'observera donc pas le comportement polymorphe
    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

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    36
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 36
    Par défaut
    Donc, pour que ça marche, il faudrait que je code :

    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
     
    class Base
    {
        public :         
            int i;
     
            virtual void f(){};
            virtual void f(const int val){};
    }
     
    class Derived : public Base
    {
        public :
            void f(const int val);
    }
     
    void Derived::f(const int val)
    {
        f();
        i = val;
    }
    C'est çà ?

  6. #6
    Membre très actif
    Homme Profil pro
    En rupture avec la societé
    Inscrit en
    Novembre 2008
    Messages
    144
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : En rupture avec la societé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 144
    Par défaut
    Citation Envoyé par titibete Voir le message
    Donc, pour que ça marche, il faudrait que je code :

    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
     
    class Base
    {
        public :         
            int i;
     
            virtual void f(){};
            virtual void f(const int val){};
    }
     
    class Derived : public Base
    {
        public :
            void f(const int val);
    }
     
    void Derived::f(const int val)
    {
        f();
        i = val;
    }
    C'est çà ?
    tu as exactement la même chose avec en plus la redéfinition de la surcharge f(const int val) et tu masque toujours f() et ces surcharges en base.

    Que cherche tu vraiment a faire avec cette exemple.

  7. #7
    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
    A peu près, si ce n'est que, dans le cas présent, Base::f (sans argument) n'a pas vraiment d'intérêt à être déclarée virtuelle, vu qu'elle n'est pas redéfinie...

    Il faut comprendre que la virtualité a un cout, entre autre, du fait du passage par une table des fonctions virtuelles (la vtable) qui permet, justement, de déterminer quelle fonction appeler effectivement.

    L'idée est donc de ne déclarer virtuelles que les fonctions qui ont de bonnes raisons de l'être

    Maintenant, nous sommes d'accords sur le fait que je ne fais que répondre à la question "pour que cela marche"...

    A coté de cela, je ne me prononce absolument pas sur l'opportunité de faire apparaitre f() ou f(int) dans l'interface de la classe de base... Et encore moins sur l'opportunité de permettre de les redéfinir dans les classes dérivées.

    Pour pouvoir se prononcer sur ces opportunité, il faudrait présenter un cas concrêt, avec des classes dont les responsabilités seraient connues et donc dont les services attendus tant par f() que par f(int) seraient clairement identifiés
    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

  8. #8
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Mais attention, ce n'est pas une redéfinition, ce qui fait que si tu écrivait purement et simplement
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void Derived::f(const int val)
    {
        f();
        i = val;
    }
    sans avoir redéfini void f() dans ta classe dérivée, cela reviendrait exactement au même (car f() est une fonction qui est tout à fait accessible depuis Derived, vu qu'elle fait partie de l'interface publique de Base )
    Si ma mémoire ne me joue pas des tours (et u test vite fait tend à le confirmer), non f() ne suffit pas (il faut bel et bien préciser Base::f()) car f() est masqué par f(int) lors du name lookup.

  9. #9
    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 gl Voir le message
    Si ma mémoire ne me joue pas des tours (et u test vite fait tend à le confirmer), non f() ne suffit pas (il faut bel et bien préciser Base::f()) car f() est masqué par f(int) lors du name lookup.
    Ah, oui, au temps pour moi...

    j'ai parlé un peu vite
    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

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

Discussions similaires

  1. appel d'une fonction à partir d'un popup
    Par villeneuvejsp dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 02/12/2004, 17h00
  2. Appel d'une fonction
    Par georgeabitbol dans le forum ASP
    Réponses: 4
    Dernier message: 08/07/2004, 14h29
  3. Réponses: 4
    Dernier message: 02/06/2004, 16h35
  4. Appel d'une fonction
    Par jfphan dans le forum ASP
    Réponses: 4
    Dernier message: 14/04/2004, 15h06
  5. A la recherche de l'appel d'une fonction...
    Par karl3i dans le forum C
    Réponses: 3
    Dernier message: 24/09/2003, 12h34

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