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 :

Héritage et surcharge de méthode ?


Sujet :

C++

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Février 2007
    Messages
    206
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 206
    Points : 79
    Points
    79
    Par défaut Héritage et surcharge de méthode ?
    Salut à tous

    J'aimerais faire dériver une classe d'une autre, et utiliser des méthodes surchargées entre les deux. Malheureusement ça ne passe pas du tout :s

    Voici le 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
    class File {
    public:
    	File(FileType type);
    	File(string path);
    	virtual ~File();
     
    	int read(int lineNumber, int & sortie);
    	int read(int lineNumber, float & sortie);
    	int read(int lineNumber, bool & sortie);
    };
     
    class FileConfig: public File {
    public:
    	FileConfig(FileType type);
    	FileConfig(string path);
    	virtual ~FileConfig();
     
    	int read(int lineNumber, string & sortie);
    	int read(int lineNumber, vector<int> & sortie);
    };
    Le code de ces deux classes compile, mais si j'essaie de les utiliser avec une autre ça plante:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    FileConfig file(CONFIG_CUR);
    int test;
    file.read(0, test); //ne compile pas
    Le compilateur me dit que la méthode FileConfig::read(int, int&); n'est pas définie

    J'ai beau chercher je ne trouve pas de solution, j'en viens à me demander si c'est possible de faire une telle surcharge.

    Merci d'avance pour vos conseils

  2. #2
    Membre régulier
    Profil pro
    Inscrit en
    Février 2007
    Messages
    206
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 206
    Points : 79
    Points
    79
    Par défaut
    Je viens de résoudre le problème par une manière des plus moches:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    fileConfig.File::read(0, test);
    Si quelqu'un a mieux, ou au moins une bonne explication, je suis preneur

  3. #3
    Membre expert Avatar de jabbounet
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juin 2009
    Messages
    1 909
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 909
    Points : 3 284
    Points
    3 284
    Par défaut
    As tu bien implémenté toutes les méthodes?
    As tu bien implémenté les desctucteurs/constructeurs que tu as déclaré.

    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
    #include <iostream>
    #include <string>
    class File {
    public:
      File(std::string &path) {
        std::cout << "File() path= " << path << std::endl;
      }
     
      virtual ~File() {
        std::cout << "~File()" << std::endl;
      }
     
      int read(int lineNumber, int & sortie) {
        std::cout << "File::read(" <<
          lineNumber << "," << sortie << ")" << std::endl;
        return 0;
      }
    };
     
    class FileConfig: public File {
    public:
      FileConfig(std::string &path) :
        File(path) {
        std::cout << "Fileconfig() path=" << path << std::endl;
      }
     
      virtual ~FileConfig() {
        std::cout << "~FileConfig()" << std::endl;
      }
    };
    int main() {
      std::string path("abcdef");
      FileConfig file(path);
      int test;
      file.read(0, test);
      test++;
      file.read(1, test);
      return 0;
    }
    Ce code fonctionne chez moi.
    bazar: http://www.improetcompagnie.com/publ...ctacles-6.html

    BÉPO la disposition de clavier francophone, ergonomique et libre: http://bepo.fr/wiki/Accueil

    Emacs Wiki: http://www.emacswiki.org/

    En attente de ce que produira: http://www.pushmid.com

  4. #4
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Février 2007
    Messages
    206
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 206
    Points : 79
    Points
    79
    Par défaut
    @jabbounet:

    Ton code fonctionne aussi chez moi, mais c'est dans le cas ou tu redéfinis ta méthode dans la classe fille, avec d'autres paramètres, que ça plante. Je ne sais pas si tu as le même résultat.

    @Laurent Gomila:

    Merci J'ai une autre question, dans le cas où ou on souhaite utiliser "using Base::F;" mais si dans la classe mère on a int F(int) et int F(bool), est-ce que ça passe ?

    Si non, on est obligé d'utiliser d.F(5), comme dans la FAQ ?

  6. #6
    En attente de confirmation mail

    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 : 33
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Quand le compilateur cherche à appeler une méthode, il commence déjà par chercher si le nom existe, si ce n'est pas le cas il passe dans la classe mère et remonte ainsi de suite, quand il en a trouvé une il s'arrete (avant même d'avoir vérifié la signature), dans ton cas il s'arrete au fonction de la classe fille.

    Ensuite il cherche dans les fonction qu'il à trouvé si il y en a une qui convient, si c'est le cas il l'appel, sinon il te renvoye une erreur. dans ton cas il te renvoye une erreur.

    Utiliser un using dans une classe fille, c'est dire que toutes les fonction avec ce nom qui appartiennent à la classe mère doivent aussi être prises en compte dans la classe fille lors de la recherche.

    Utiliser l'opérateur de résolution de portée (:: ) c'est indiqué où le compilateur doit chercher.

    Donc si tu as plusieurs fonctions qui porte le même nom, avec le using elles seront toutes "dépplacés" dans la classe fille et donc tu pourras toutes les appeler directement, avec la seconde méthode il faudra préciser à chaque fois.

  7. #7
    Membre expert Avatar de jabbounet
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juin 2009
    Messages
    1 909
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 909
    Points : 3 284
    Points
    3 284
    Par défaut
    La même en re-définissant la même méthode dans la classe fille/mère
    j'arrive indiférrament a appeler la méthode de la classe mère ou de la classe fille.

    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
    #include <iostream>
    #include <string>
    class File {
    public:
      File(std::string &path) {
        std::cout << "File() path= " << path << std::endl;
      }
      virtual ~File() {
        std::cout << "~File()" << std::endl;
      }
      int read(int lineNumber, int & sortie) {
        std::cout << "File::read(" <<
          lineNumber << "," << sortie << ")" << std::endl;
        return 0;
      }
    };
     
    class FileConfig: public File {
    public:
      FileConfig(std::string &path) :
        File(path) {
        std::cout << "Fileconfig() path=" << path << std::endl;
      }
      virtual ~FileConfig() {
        std::cout << "~FileConfig()" << std::endl;
      }
      int read(int lineNumber, int & sortie) {
        std::cout << "FileConfig::read(" <<
          lineNumber << "," << sortie << ")" << std::endl;
        return 0;
      }
    };
     
    int main() {
      std::string path("abcdef");
      FileConfig file(path);
      int test;
      file.read(0, test);
      test++;
      file.File::read(1, test);
      return 0;
    }
    g++ readx.cpp -o readx && ./readx
    File() path= abcdef
    Fileconfig() path=abcdef
    FileConfig::read(0,0)
    File::read(1,1)
    ~FileConfig()
    ~File()
    Compilation finished at Mon Oct 4 20:40:24
    bazar: http://www.improetcompagnie.com/publ...ctacles-6.html

    BÉPO la disposition de clavier francophone, ergonomique et libre: http://bepo.fr/wiki/Accueil

    Emacs Wiki: http://www.emacswiki.org/

    En attente de ce que produira: http://www.pushmid.com

  8. #8
    En attente de confirmation mail

    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 : 33
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    @jabbounet: Ceci pour faire simple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    struct A { void foo(){} };
    struct B : A { void foo(int){} };
    Ne marche pas si tu tente d'appeler foo() sur un objet de type statique B.
    Tes code ne montre pas ce problème (absence de masquage ou paramètre identique).

  9. #9
    Membre expert Avatar de jabbounet
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juin 2009
    Messages
    1 909
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 909
    Points : 3 284
    Points
    3 284
    Par défaut
    Citation Envoyé par Flob90 Voir le message
    @jabbounet: Ceci pour faire simple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    struct A { void foo(){} };
    struct B : A { void foo(int){} };
    Ne marche pas si tu tente d'appeler foo() sur un objet de type statique B.
    Tes code ne montre pas ce problème (absence de masquage ou paramètre identique).
    scheme au départ n'indique pas qu'il utilise un objet statique.


    dans le second exemple il y'a cette méthode qui est déclarée à la fois dans la classe mère et dans la classe fille.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
      int read(int lineNumber, int & sortie) {...}
    bazar: http://www.improetcompagnie.com/publ...ctacles-6.html

    BÉPO la disposition de clavier francophone, ergonomique et libre: http://bepo.fr/wiki/Accueil

    Emacs Wiki: http://www.emacswiki.org/

    En attente de ce que produira: http://www.pushmid.com

  10. #10
    Membre régulier
    Profil pro
    Inscrit en
    Février 2007
    Messages
    206
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 206
    Points : 79
    Points
    79
    Par défaut
    Merci de toutes vos explications, j'ai bien bien compris maintenant

  11. #11
    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 : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Citation Envoyé par jabbounet Voir le message
    scheme au départ n'indique pas qu'il utilise un objet statique.
    Pas un objet statique (i.e. déclaré static) mais un oubjet dans le type statique est la classe file. Ce qui apparait dans l'exemple d'appel :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    FileConfig file(CONFIG_CUR);
    int test;
    file.read(0, test); //ne compile pas
    Le type de file est bien FileConfig et non File.

    Citation Envoyé par jabbounet Voir le message
    dans le second exemple il y'a cette méthode qui est déclarée à la fois dans la classe mère et dans la classe fille.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
      int read(int lineNumber, int & sortie) {...}
    Non justement dans les exemples de scheme, ce n'est pas cette fonction qui est déclarée à la fois dans la classe mère et dans la classe fille. Mais des fonction ayant le même nom mais une liste de paramètres différente.

    Pour la classe mère :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    	int read(int lineNumber, int & sortie);
    	int read(int lineNumber, float & sortie);
    	int read(int lineNumber, bool & sortie);
    Et pour la fille :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    	int read(int lineNumber, string & sortie);
    	int read(int lineNumber, vector<int> & sortie);
    Et c'est bien là que se situe son problème.

  12. #12
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 611
    Points
    30 611
    Par défaut
    Salut,

    Ceci dit, je me demande si l'héritage est réellement opportun dans le cas présent

    Je m'explique avant que tout le monde ne commence à me crier dessus:

    La classe File ne représente pas un fichier comme son nom semble pourtant l'indiquer, mais un lecteur de fichier : un système permettant de désérialiser une information donnée.

    De son coté, la classe ConfigFile ne représente pas plus un fichier que la classe File, mais un gestionnaire d'information (dé)sérialisables.

    Pour remplir sa (ses) collection(s) d'informations, il devrait donc faire appel à une instance cohérente de File, mais il n'y a aucune raison qu'il soit considéré comme un objet de type File, le mal nommé.

    Il y a d'ailleurs de fortes chances pour que les fonctions que l'on souhaite appeler depuis une instance de ConfigFile soient, tout simplement load() (ou read() ) et save() (ou write() ) mais... sans aucun arguments, du moins, si on ne s'intéresse qu'aux fonctions de lecture/ d'écriture des données .

    Il me semble, en effet, bien plus opportun de lire (ou d'écrire) l'intégralité des données "en une seule fois" plutôt que de vouloir les lire (ou les écrire) à chaque fois que l'on en a besoin, parce que:

    1- Il suffit que l'on décide de rajouter une information pour... aller "foutre le bordel" au niveau des numéros de lignes

    2- Il ne faut pas oublier qu'un fichier est "gravé dans le marbre" lors de l'écriture: Scheme ne présente ici que la possibilité de lire une information, mais, il semble oublier que, avant de pouvoir lire une information, il faut... qu'elle ait été écrite au préalable

    Et il ne faut pas oublier qu'une configuration est, par nature, susceptible d'être modifiée

    3- Les accès disques sont particulièrement lents par rapport aux accès mémoire, surtout s'il faut commencer à lire un nombre inconnu de données avant d'accéder à celle qui nous intéresse.

    En lisant les données une bonne fois pour toutes, on gagnera fatalement en performances, sans que cela n'ait quoi que ce soit à voir avec de l'optimisation prématurée

    4- Si, pour une raison ou une autre, on a besoin plusieurs fois de la même information, il serait dommage (et surtout lent à exécuter) d'aller à chaque fois la relire dans le fichier

    Au final, si on peut envisager de garder le nom de ConfigFile bien que Config ou ConfigManager me semblerait plus opportun), et cette classe ne devrait, à mon sens, pas hériter de la classe File qui porterait un nom bien plus en rapport avec ce que l'on attend d'elle si on la renommait en FileReader, par exemple

    Mais bien sur, ce n'est ici que mon avis

    EDIT : D'ailleurs, il ne me semble pas vraiment opportun de fournir le numéro de ligne aux différentes versions de read dans la (toujours mal nommée) classe File:

    Etant donné que l'on partirait du principe de lire l'intégralité des données "d'une seule traite", les possibilités qui s'offrent à nous seraient:
    • D'ouvrir le fichier au moment de la création de l'instance du type mal nommé File, ou
    • D'ouvrir le fichier au début de la fonction read de ConfigFile et, dans ce cas,
    • de transmettre le fichier à la fonction read de l'instance de File
    En effet, les flux gardent d'eux-même la position atteinte suite aux lectures.

    Si l'idée est, de toutes manière, de lire l'intégralité du fichier, autant profiter de cet état de fait
    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. Héritage multiple, surcharge de méthodes, etc
    Par Stnaire dans le forum jQuery
    Réponses: 0
    Dernier message: 04/03/2012, 01h25
  2. [POO] Héritage et surcharge de méthodes
    Par defkid dans le forum Langage
    Réponses: 4
    Dernier message: 26/02/2007, 15h51
  3. [POO] Surcharge de méthode
    Par ouioui2000 dans le forum Langage
    Réponses: 4
    Dernier message: 09/03/2006, 16h25
  4. [Custom Tags] Problème avec une surcharge de méthode
    Par Strab dans le forum Taglibs
    Réponses: 19
    Dernier message: 26/08/2005, 17h34
  5. Comment surcharger la méthode OnClose d'un TFrame ?
    Par sdebrois dans le forum Composants VCL
    Réponses: 2
    Dernier message: 17/01/2005, 21h57

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