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 :

surdéfinition de fonction et héritage


Sujet :

C++

  1. #1
    Membre émérite
    Homme Profil pro
    Inscrit en
    Décembre 2007
    Messages
    758
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France

    Informations professionnelles :
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Décembre 2007
    Messages : 758
    Par défaut surdéfinition de fonction et héritage
    Bonjour,

    tout d'abord désolé, je ne suis pas encore habitué à la terminologie exacte du coup mon titre ne correspond peut être pas tout à fait à mon problème. et ça me pose aussi un problème pour questionner notre meilleur ami commun.

    comme promis je reviens vous embêter . je progresse doucement mais sûrement dans mon apprentissage mais je bloque sur un point.

    Voici mon 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
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    #include <iostream>
    #include <map>
    #include <string>
     
    using namespace std;
     
    class Item
    {
    	public:
     
    	Item(int id) : id(id)
    	{
    	}
     
    	int get_id()
    	{
    		return id;
    	}
     
    	void set_id(int newid)
    	{
    		id=newid;
    	}
     
    	private:
     
    	int id;
    };
     
    class NamedItem : public Item
    {
    	public:
     
    	NamedItem(int id,string name) : Item(id), name(name)
    	{
    	}
     
    	string get_name()
    	{
    		return name;
    	}
     
    	void set_name(string newname)
    	{
    		name=newname;
    	}
     
    	private:
     
    	string name;
    };
     
    class Items
    {
    	public:
     
    	Items()
    	{
    	}
     
    	void add(Item* item)
    	{
    		int id=item->get_id();
    		dict[id]=item;
    	}
     
    	void add(Item& item)
    	{
    		add(&item);
    	}
     
    	Item* get(int id)
    	{
    		return dict[id];
    	}
     
    	private:
     
    	map<int,Item*> dict;
    };
     
    class NamedItems : public Items
    {
    	public:
     
    	NamedItems() : Items()
    	{
    	}
     
    	//NamedItem* get(int id)
    	//{
    	//	//comment redéfinir Items::get pour avoir un NamedItem* en résultat ?
    	//}
    };
    Pour résumer un peu mon problème:

    - j'ai défini une classe Item et une classe NamedItem qui dérive de Item.

    - j'ai défini une classe Items qui est un "conteneur" d'Item et une classe NamedItems qui dérive de Items et qui est un "conteneur" de NamedItem.

    - lorsque j'utilise la méthode add de NamedItems (qui est en fait celle de sa classe mère Items) je donne un objet de type NamedItem* en argument et cela fonctionne car NamedItem dérive de Item (ça c'est si j'ai bien tout compris)

    - j'ai défini une méthode get dans Items qui revoie un Item*.

    - j'aimerais surdéfinir cette fonction dans la classe NamedItems afin qu'elle renvoit un NamedItem* et je ne sais pas comment faire. Et le vrai problème c'est que je ne sais pas si j'ai ce problème parce que j'ai mal conçu le biniou ou si c'est parce qu'un concept POO m'échappe encore ?

    - sans surdéfinir cette fonction, elle me renvoit un Item* sur lequel je peux effectuer des méthodes liées à la classe Item mais pas les méthodes liées à la classe NamedItem.

    J'espère avoir expliqué suffisamment clairement mon problème.

    Merci pour votre aide

  2. #2
    Membre Expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Par défaut
    D'abord, est-ce que mettre les membres des classes en protected ne serait pas plus pratique?

    Sinon, pour ton problème, normalement tu peux faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
     
    NamedItem* get(int id)
    {
       return Items::get( id );
    }
     
    // ou bien
     
    NamedItem* get(int id)
    {
       return static_cast<NamedItem*>( Items::get( id ) );
    }
    (je n'ai pas compilé pour être certain, mais l'un ou l'autre devrait marcher.

    Ce que je fais ici, c'est appeler explicitement la version de Items de get et simplement de caster (implicitement dans la première version, mais je suis pas sur que ça passe a la compilation) le pointeur dans le bon type.

    Evidemment, je pars du principe que je sais que get retourne un NamedItem.

    Le problème c'est que si c'est pas le cas, tu vas mentir au compilateur, et donc te retrouver potentiellement avec un comportement indéfini.

    En fait ce que je ne comprends pas, c'est quel est l'interet de la classe NamedItems?

  3. #3
    Membre émérite
    Homme Profil pro
    Inscrit en
    Décembre 2007
    Messages
    758
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France

    Informations professionnelles :
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Décembre 2007
    Messages : 758
    Par défaut
    wow merci, je venais justement de trouver ce static_cast et effectivement ça marche bien mais je ne sais pas si c'est très propre.

    pour le premier cas que tu donnes j'avais essayé et mon compilateur m'envoit sur les rosiers avec une insulte: cannot convert from 'class Item *' to 'class NamedItem *'.

    l'interêt de la classe NamedItems dans le cas que je donne il est pas évident c'est certain mais j'ai essayé d'isoler au maximum mon problème. dans mon programme complet les classes sont très différentes mais le problème est le même.

    ensuite mettre le map en protected oui c'est une solution mais du coup je n'utilise plus le get de Items.

    j'ai lu (dans le Apprendre C++ de Claude Delannoy) qu'il était possible de surdéfinir get en utilisant deux fonctions virtuelles (dans Items et NamedItems) mais je n'arrive pas à le mettre en pratique. L'exemple du livre est donné avec des références et lorsque je j'essaie de transposer avec des pointeurs dans mon cas j'ai une belle insulte: "overriding virtual function differs from 'Items::get' only by return type or calling convention"

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    class Y : public X {...}; // Y dérive de X
    class A
    {public :
    virtual X & f(int);
    };
    class B : public A
    {public :
    virtual Y & f(int);
    }
    De plus je ne saisis pas bien comment je pourrais me passer d'une conversion de pointeur avec static_cast même en utilisant ces fonctions virtuelles.

    Autre point encore plus gênant, si je comprends bien ce qu'il y a écrit dans le bouquin ma surdéfinition est incorrecte car mes 2 fonctions ont la même signature (même nom et même argument). Pourquoi mon compilateur ne me dit rien ?

    Si je résume, j'ai à priori 2 solutions:

    - mettre le map dict en protected et accéder à ce dict depuis NamedItems::get mais cela revient à réécrire la fonction
    - utiliser une conversion de type avec static_cast et ça me permet de déléguer à Items l'accès au map dict (à priori je devrais être obligé d'utiliser des fonctions virtuelles dans ce cas).

    Comme je suis un vrai débutant et que j'apprends avec des livres et google, j'ai envie de prendre les bonnes habitudes dès le départ

    Et je me retrouve en prime avec une question de plus concernant mon compilateur (visual c++ 6.0 dont je n'ai pas forcément entendu que du bien) je vais peut être voir à changer.

    Merci pour ton aide en tout cas !

  4. #4
    Membre Expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Par défaut
    Je n'avais même pas remarqué qu'il n'y avait pas de virtual.

    Je pense aussi que tu aurais du avoir un warning mais comme la signature n'est pas exactement la même, peut être que vc considère que c'est pas dangereux. Je connais au moins un autre compilo qui aurait mis un warning.

    Sinon, ce qui est expliqué dans ton bouquin c'est que tu peux faire ç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
    39
    40
    41
    42
    43
     
    class Items
    {
    public:
     
    	Items()
    	{
    	}
     
    	void add(Item* item)
    	{
    		int id=item->get_id();
    		dict[id]=item;
    	}
     
    	void add(Item& item)
    	{
    		add(&item);
    	}
     
    	virtual Item* get(int id) // ici en virtual
    	{
    		return dict[id];
    	}
     
    private:
     
    	map<int,Item*> dict;
    };
     
    class NamedItems : public Items
    {
    public:
     
    	NamedItems() : Items()
    	{
    	}
     
    	NamedItem* get(int id); // ici seulement la déclaration
    	/*{
    		return static_cast< NamedItem* >( Items::get( id ) );
    	}*/
    };
    De cette manière tu n'as pas a écrire le code, juste a donné une signature qui va faire automatiquement le static_cast.

    edit> Rectification : après vérification ça passe pas au link. Je me disais bien aussi que ça pouvait pas marcher...


    Oublie la suggestion de protected.

    VC6.0 est dépassé surtout si tu veux utiliser des templates.
    Les derniers compilateurs de microsoft sont disponible gratuitement : cherche visual studio express .


    edit2> J'ajoute une remarque : ton get n'est pas protégé au sens ou si tu demande un élément qui n'existe pas tu vas te retrouver avec un pointeur non initializé. Dans le get de Items tu devrais ajouter une vérification voir si l'element existe bien dans la map et ensuite retourner le pointeur vers cet élément ou null.

Discussions similaires

  1. Réponses: 2
    Dernier message: 29/03/2007, 12h02
  2. [POO] Pointeur sur fonction membre et héritage
    Par MrDuChnok dans le forum C++
    Réponses: 9
    Dernier message: 20/07/2006, 17h19
  3. Réponses: 6
    Dernier message: 12/07/2006, 19h29
  4. [G++] Héritage et surcharge de fonction
    Par Beuss dans le forum Autres éditeurs
    Réponses: 11
    Dernier message: 15/05/2006, 09h18
  5. héritages multiples et fonctions abstraites
    Par julien.sagnard dans le forum C++
    Réponses: 4
    Dernier message: 21/10/2005, 14h58

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