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++Builder Discussion :

Appel d'une fonction redéfinie


Sujet :

C++Builder

  1. #1
    Membre régulier
    Inscrit en
    Avril 2004
    Messages
    249
    Détails du profil
    Informations personnelles :
    Âge : 53

    Informations forums :
    Inscription : Avril 2004
    Messages : 249
    Points : 112
    Points
    112
    Par défaut Appel d'une fonction redéfinie
    Salut,

    Voilà le topo :

    J'ai une classe de base définissant quelques fonctions, et j'ai deux classes dérivées de cette classe de base.
    Certaines fonctions de la classe de base sont redéfinies dans les classes dérivées.

    J'ai un soucis concernant l'appel aux fonctions qui existent dans la classe de base et qui sont redéfinies, et ceci depuis les classes dérivées.

    Voilà un peu de code :

    base.h :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    protected:
        virtual int __fastcall LireSurPortCOM(BYTE *dcReponseParam, DWORD TimeOut, bool DoAcquit);
    base.cpp :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    int __fastcall TBase::LireSurPortCOM(BYTE *dcReponseParam, DWORD TimeOut, bool DoAcquit)
    {
        return 0;
    }
    derivee.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    private:
        int __fastcall LireSurPortCOM(BYTE *dcReponseParam, DWORD TimeOut, bool DoAcquit);
        int __fastcall FaireTransfert();
    derivee.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    int __fastcall TDerivee::LireSurPortCOM(BYTE *dcReponseParam, DWORD TimeOut, bool DoAcquit)
    {
        bla bla bla
        return result;
    }
     
    int __fastcall TDerivee::FaireTransfert()
    {
        int result = LireSurPortCOM(paramètres...);
        return result;
    }
    Dans mon mainform, je fais ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    TBase *b = new TBase();
    TDerivee *d = (TDerivee *)b;
    d->FaireTransfert();
    La fonction FaireTransfert() est bien appelée depuis la classe dérivée (puisqu'elle lui est propre).
    Par contre, dans la fonction FaireTransfert() elle-même, l'appel à la fonction LireSurPortCOM passe par la fonction de la classe de base et non la fonction redéfinie !

    J'ai loupé quelque chose ?
    _____
    __
    _

    Engi

  2. #2
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Points : 1 878
    Points
    1 878
    Billets dans le blog
    21
    Par défaut
    TDerivee *d = (TDerivee)b;
    là si ton compilateur ne détecte pas une erreur c'est qu'il y a un problème: TDerivee n'est pas un type pointeur, donc le cast de b (qui est un TBase*) en TDerived devrait clocher.

    si c'est une faute de frappe regarde s'il n'y en a pas d'autres dans ton code parce que c'est en effet la fonction dérivée qui devrait être appelée.

    Aucune chance que le "blabla" retourne effectivement 0 dans la fonction dérivée?

  3. #3
    Membre régulier
    Inscrit en
    Avril 2004
    Messages
    249
    Détails du profil
    Informations personnelles :
    Âge : 53

    Informations forums :
    Inscription : Avril 2004
    Messages : 249
    Points : 112
    Points
    112
    Par défaut
    C'était effectivement une faute de frappe que je viens de corriger.
    L'appel à la fonction LireSurportCOM depuis FaireTransfert me retourne bien 0.
    J'ai la certitude que c'est la fonction LireSurportCOM de la classe de base qui est exécutée car j'ai exécuté mon programme en pas à pas pour voir comment ça se passait.
    Sachant que la fonction LireSurportCOM est redéfinie dans la classe dérivée, pourquoi un appel à cette fonction depuis la classe dérivée exécute celle de la classe de base ?
    _____
    __
    _

    Engi

  4. #4
    Membre régulier
    Inscrit en
    Avril 2004
    Messages
    249
    Détails du profil
    Informations personnelles :
    Âge : 53

    Informations forums :
    Inscription : Avril 2004
    Messages : 249
    Points : 112
    Points
    112
    Par défaut
    Info supplémentaire :
    Mon problème ne se pose que lorsque j'appelle ma fonction depuis un pointeur de type TBase * casté en TDerivee *.

    Si je fais :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    TDerivee *d = new TDerivee();
    d->FaireTransfert();
    Dans ce cas, c'est bien la fonction LireSurPortCOM redéfinie dans la classe dérivée qui est exécutée dans FaireTransfert()
    _____
    __
    _

    Engi

  5. #5
    Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2011
    Messages
    35
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Septembre 2011
    Messages : 35
    Points : 47
    Points
    47
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    TBase *b = new TBase();
    TDerivee *d = (TDerivee *)b;
    d->FaireTransfert();
    es-tu sure que ton code fonctionne?
    Tu peux faire un TBase *d = new TDerivee(); et la ça marchera.
    Ce n'est pas bon de caster une classe mère vers une classe fille si à la création tu ne précise pas que c'est une classe fille, l'inverse est possible mais normalement ta classe fille va rajouter des éléments que ta classe mère n'a pas et dans ton cas tu alloues la mémoire pour une TBase qui ne fait pas forcement la même taille et sera certainement plus petite que ta classe fille.
    Après si tu as bien alloué comme je fais moi, tu peux totalement dérivé le d vers la classe fille TDerivee car elle aura déjà alloué la bonne espace mémoire.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    TBase *b = new TDerivee ();
    TDerivee *d = (TDerivee *)b;
    d->FaireTransfert()
    La ça devrait fonctionner.

  6. #6
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Points : 1 878
    Points
    1 878
    Billets dans le blog
    21
    Par défaut
    Je n'arrive pas à reproduire le problème. J'ai compilé:

    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
    #include <iostream>
     
    class Base {
      protected:
      virtual const char* bla() { return "base blabla"; }
      };
     
    class Derived {
      public:
      void parle() { std::cout << chuchote() << std::endl; }
      private:
      const char* bla() { return "derived blabla"; }
      const char* chuchote() { return bla(); }
     
      };
     
    int main() {
     
      Base* b = new Base();
      Derived* d = (Derived*) b;
      d->parle();
     
    }
    et la sortie est bien "derived blabla".

    Dans l'ignorance de ce qui se passe vraiment, je te propose d'essayer de remplacer ton cast C par un cast C++, en l'occurrence par un dynamic_cast qui est fait pour ce genre de conversions

  7. #7
    Membre régulier
    Inscrit en
    Avril 2004
    Messages
    249
    Détails du profil
    Informations personnelles :
    Âge : 53

    Informations forums :
    Inscription : Avril 2004
    Messages : 249
    Points : 112
    Points
    112
    Par défaut
    Citation Envoyé par stendhal666 Voir le message
    Je n'arrive pas à reproduire le problème. J'ai compilé:

    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
    #include <iostream>
     
    class Base {
      protected:
      virtual const char* bla() { return "base blabla"; }
      };
     
    class Derived {
      public:
      void parle() { std::cout << chuchote() << std::endl; }
      private:
      const char* bla() { return "derived blabla"; }
      const char* chuchote() { return bla(); }
     
      };
     
    int main() {
     
      Base* b = new Base();
      Derived* d = (Derived*) b;
      d->parle();
     
    }
    et la sortie est bien "derived blabla".

    Dans l'ignorance de ce qui se passe vraiment, je te propose d'essayer de remplacer ton cast C par un cast C++, en l'occurrence par un dynamic_cast qui est fait pour ce genre de conversions
    Effectivement, je viens de tester ton code et cela fonctionne.
    Ceci étant, c'est normal car ta classe "Derived" n'est pas dérivée de la classe "Base".
    Déclare la classe "Derived" comme cela :
    et tu verras que tu auras le même problème que moi.

    Et pour ce qui est du dynamic_cast, j'avais essayé mais il me retourne un pointeur nul.
    _____
    __
    _

    Engi

  8. #8
    Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2011
    Messages
    35
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Septembre 2011
    Messages : 35
    Points : 47
    Points
    47
    Par défaut
    As-tu lu mon poste (2 postes au dessus)?

  9. #9
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Points : 1 878
    Points
    1 878
    Billets dans le blog
    21
    Par défaut
    Effectivement, je viens de tester ton code et cela fonctionne.
    Ceci étant, c'est normal car ta classe "Derived" n'est pas dérivée de la classe "Base".

    C'est bien vrai

    D'un autre côté, tu crées un objet Base et tu veux qu'il se comporte comme un Derived, donc on est deux... A la réflexion, ce qui se passe est tout à fait normal! Le polymorphisme, c'est que le pointeur choisisse la fonction en fonction de l'objet sur lequel il pointe, pas qu'une base se transforme magiquement en derived quand tu mets un pointeur derived dessus. C'est pour ça que dynamic_cast renvoie null: ce n'est pas le chemin à prendre!

  10. #10
    Membre régulier
    Inscrit en
    Avril 2004
    Messages
    249
    Détails du profil
    Informations personnelles :
    Âge : 53

    Informations forums :
    Inscription : Avril 2004
    Messages : 249
    Points : 112
    Points
    112
    Par défaut
    Citation Envoyé par darkhades Voir le message
    As-tu lu mon poste (2 postes au dessus)?
    Oui, mais ta solution me pose problème ou alors j'ai mal conçu mon programme.
    En fait, c'est un peu plus compliqué que ce que j'ai exposé dans ma question première.

    Mon programme consiste à communiquer avec des matériels connectés à un modem.
    J'ai à ma disposition deux types de modem avec des caractéristiques communes et certaines qui leur sont propres, d'où l'idée d'une classe de base et deux classes dérivées.
    Le problème, c'est que mon programme doit communiquer avec ces fameux matériels, mais sans connaitre à l'avance le type de modem utilisé.
    C'est pour cela que mon programme instancie un objet modem dont le type est la classe de base.
    Ne connaissant pas le type de modem, je ne peux pas instancier l'objet en partant d'une des classes dérivées.

    L'idée est de partir de la classe de base, de la caster vers une classe de type dérivée, d'appeler une fonction de communication bien précise, qui ne peut être comprise que par un seul type de modem.
    Si j'obtiens une réponse, j'en déduis que le modem connecté est du type de la classe dérivée utilisée, sinon, c'est l'autre type.
    _____
    __
    _

    Engi

  11. #11
    Membre régulier
    Inscrit en
    Avril 2004
    Messages
    249
    Détails du profil
    Informations personnelles :
    Âge : 53

    Informations forums :
    Inscription : Avril 2004
    Messages : 249
    Points : 112
    Points
    112
    Par défaut
    Citation Envoyé par stendhal666 Voir le message

    C'est bien vrai

    D'un autre côté, tu crées un objet Base et tu veux qu'il se comporte comme un Derived, donc on est deux... A la réflexion, ce qui se passe est tout à fait normal!
    C'est certainement par méconnaissance de ma part, mais je pensais qu'une classe dérivée n'utilisait que les fonctions qui lui sont propres ou bien celles redéfinies (dans ce cas, en ignorant celles de la classe de base déclarées virtuelles). C'est vrai dans un cas.

    Mais, dans mon cas :
    - Sachant que mon objet est à l'origine déclaré avec comme type la classe de base
    - Même si le pointeur que j'utilise est du type de la classe dérivée
    -> Je pensais que dans ce cas, les fonctions appelées seraient celles de la classe dérivée.

    Manifestement, ce n'est pas le cas.
    C'est certainement cela qu'on appelle le polymorphisme mais j'avoue ne pas avoir beaucoup potassé dans ce domaine et il va donc falloir que je révise un peu cette notion :o)
    _____
    __
    _

    Engi

  12. #12
    Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2011
    Messages
    35
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Septembre 2011
    Messages : 35
    Points : 47
    Points
    47
    Par défaut
    Pourquoi tu ne ferais pas le contraire?
    Tu as deux classes bases qui sont tes modems et une classe dérivé qui hérite des 2. Dans la methode hérité FaireTransfert() tu appelles celui du parent.
    Donc il appellera normalement la bonne méthode du parent ne sachant pas par contre quel type c'est.

  13. #13
    Membre régulier
    Inscrit en
    Avril 2004
    Messages
    249
    Détails du profil
    Informations personnelles :
    Âge : 53

    Informations forums :
    Inscription : Avril 2004
    Messages : 249
    Points : 112
    Points
    112
    Par défaut
    Citation Envoyé par darkhades Voir le message
    Pourquoi tu ne ferais pas le contraire?
    Tu as deux classes bases qui sont tes modems et une classe dérivé qui hérite des 2. Dans la methode hérité FaireTransfert() tu appelles celui du parent.
    Donc il appellera normalement la bonne méthode du parent ne sachant pas par contre quel type c'est.
    Il faut que je remette tout ça à plat.
    En tous les cas, merci de ton aide.
    Et merci aussi à stendhal666.
    _____
    __
    _

    Engi

  14. #14
    Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2011
    Messages
    35
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Septembre 2011
    Messages : 35
    Points : 47
    Points
    47
    Par défaut
    De rien
    Si tu as besoin d'aide n'hésite pas à m'envoyer un MP. Je réponds normalement assez rapidement.

Discussions similaires

  1. appel d'une fonction surchargée
    Par titibete dans le forum Langage
    Réponses: 15
    Dernier message: 14/11/2010, 10h33
  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