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

 C++ Discussion :

Problème : héritage et polymorphisme


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti

    Profil pro
    Inscrit en
    Juin 2005
    Messages
    52
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 52
    Par défaut Problème : héritage et polymorphisme
    Bonjour,

    Je débute en c++, mais je programme déjà depuis quelques années en Java.

    J'ai un problème de compilation lorsque j'appel un méthode définie dans la super classe sur une instance de la sous classe.
    Voici un extrait du 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
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
     
    #include <iostream>
    using namespace std;
    class A {
    public:
    	A() {
    	}
    	bool add(int & element) {
    		cout << "A::add(int)" << endl;
    		return true;
    	}
    };
     
    class B : public A {
     
    public:
    	B() : A() {
    	}
    	void add(int index, int & element) {
    		cout << "B::add(int,int)" << endl;
    	}
    };
     
    int main() {
    	B b = B();
    	int element = 6;
    	bool added = b.add(element);
    	if (added) {
    		cout << "Added" << endl;
    	} else {
    		cout << "Not added" << endl;
    	}
    	return 0;
    }
    Je compile la classe avec le compilateur de visual studio 2008 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    $ cl -c -EHsc test.cpp
    test.cpp
    test.cpp(26) : error C2660: 'B::add' : function does not take 1 arguments
    Je ne comprends pas pourquoi une instance de B ne peut pas exécuter la méthode add(int) alors qu'elle est définie dans la super classe.
    On dirait que B::add(int, int&) masque la méthode A::add(int&)

    Merci d'avance pour vos réponses.

  2. #2
    Membre Expert Avatar de Astraya
    Homme Profil pro
    Consommateur de café
    Inscrit en
    Mai 2007
    Messages
    1 048
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Consommateur de café
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 1 048
    Par défaut
    Je ne comprends pas pourquoi une instance de B ne peut pas exécuter la méthode add(int) alors qu'elle est définie dans la super classe.
    On dirait que B::add(int, int&) masque la méthode A::add(int&)
    Parce que ton instance est un B. Pour utiliser le polymorphisme, tu dois le réaliser avec un pointeur ou une référence. Ce que tu réalises actuellement, c'est un b par défaut, puis une copie d'un B temporaire dans ton b.
    Pour réalisé ton polymorphisme tu dois le faire comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    A * b = new B;
    //blablablabla
    delete b;
    Nota: n'oublie pas de mettre le destructeur de A virtuel.

  3. #3
    Membre averti

    Profil pro
    Inscrit en
    Juin 2005
    Messages
    52
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 52
    Par défaut
    Je suis d'accord avec ta réponse, mais c'est un peu contradictoire avec la notion d’héritage.

    En effet l'héritage permet d'ajouter des nouvelles fonctionnalités à une classe or quand on a un objet B nous devrions avoir accès aux fonctionnalités de A.

    Ton exemple est correct mais cela reviens à faire :
    Or l’intérêt de faire une classe B est la possibilité d'appeler les méthodes de A
    or le code si dessous ne fonctionne pas.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    B * b = new B()
    b->add(5);

  4. #4
    Membre Expert

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Par défaut
    Tu es en train d'expérienter le masquage des fonctions.

    Quand tu fais un appel à une fonction (lié à une classe dans notre cas) disnon a.foo(), le compilateur regarde dans le scope de la classe de l'objet a (via le type statique), si il y a une telle fonction (il regarde jsute le nom), si c'est le cas il s'arrete sinon il continue dans les classes mères (*).

    Un fois qu'il s'est arreté il regarde si une signature peut correspondre (soit directement, soit par transtypage), si c'est le cas il l'utilise (**), sinon tu as une erreur.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    struct A
    { void foo() {} };
     
    struct B : A
    { void foo(int) {} };
     
    A a; B b; A* p = new B();
    a.foo(); a.foo(0); //1 compile, 2 ne compile pas
    b.foo(); b.foo(0); //1 ne compile pas [1], 2 compile
    p->foo(); p->foo(0); //[2] 1 compile, 2 ne compile pas
    [1] Le type statique de b est B, or dans la définition de la classe B il y a une fonction qui s'appelle foo, donc il s'arrete là mais la signature ne correspond pas : erreur
    [2] Je ne détaille pas, mais il ne faut pas oublier que le type statique de *p est A et non B

    (*) Je ne détaille pas, mais il y a tout une remonté progressive des scopes qui est effectuée, jusqu'à atteindre le namespace global, pour les fonctions libres, il faut rajouter d'autre méchanisme qui prend en compte le scope où sont les définitions des arguments, cf Koenig Lookup.

    (**) A ce niveau intervient le polymorphisme, qui indique au compilateur si il doit faire la liaison entre la fonction trouvé et l'appel ou si il doit laisser cette tache pour plus tard (liaison dynamique qui prend en compte le type dynamique de l'objet).

    Edit: J'oubliais le plus important, pour pallier à ceci tu peux indiquer au compilateur de prendre en compte les fonctions de la classes mère via une instruction using :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    struct A
    { void foo() {} };
     
    struct B : A
    { using A::foo; void foo(int) {} };

  5. #5
    Membre averti

    Profil pro
    Inscrit en
    Juin 2005
    Messages
    52
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 52
    Par défaut
    Ok pour la clause using ça reponds à mon attente mais pourquoi devoir le dire explicitement ?...

    En Java, quand on définie des méthodes publiques dans une super classes celles-ci sont disponibles dans la classe fille.

    Je pensais que c'était la même chose en C++

  6. #6
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    C'est le cas ... si tu ne les masques pas

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

Discussions similaires

  1. Problème de mise en oeuvre de l'héritage et polymorphisme
    Par jeanjean6 dans le forum Débuter avec Java
    Réponses: 4
    Dernier message: 24/05/2010, 20h35
  2. Problème avec le polymorphisme
    Par Vitis_Alba dans le forum C++
    Réponses: 14
    Dernier message: 15/01/2007, 16h41
  3. [POO] Problème héritage des classes PHP4
    Par zana74 dans le forum Langage
    Réponses: 2
    Dernier message: 15/08/2006, 16h00
  4. Problème Héritage JavaScript
    Par Flavien dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 10/07/2006, 13h29
  5. Problème héritage CWnd
    Par ptitJP dans le forum MFC
    Réponses: 4
    Dernier message: 21/04/2006, 11h41

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