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 :

[POO] Héritage et fonction non implémentée


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    256
    Détails du profil
    Informations personnelles :
    Localisation : Etats-Unis

    Informations forums :
    Inscription : Juin 2002
    Messages : 256
    Par défaut [POO] Héritage et fonction non implémentée
    Bonjour,

    Je rencontre un problème avec l'héritage, et j'avoue qu'il me dépasse complétement. La situation est très simple : j'ai trois classes appellées PluginsManager, BaseRenderer, et Dummy. Elles sont définies comme suit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    class PluginsManager
    {...}; //pour les dll
     
    class BaseRenderer : public PluginsManager
    {...
     
     void Hello() { MessageBox(NULL,"Hello","Ici",0);}
    };
     
     
    class Dummy : public PluginsManager
    { }; //diverses fonctions, mais PAS Hello
    Puis dans ma DLL, j'ai une fonction register prenant en argument un pointeur sur BaseRenderer :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    DLLEXPORT void register( BaseRenderer* _b )
    {
     _b->Hello();
    }
    que je lance via :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
     
     PluginsManager Pm;
     .. //Initialisations de Pm;
     
     Pm->register( new BaseRenderer() );
    Ca fonctionne parfaitement. Mais le problème, c'est que ça fonctionne tout autant si je remplace new BaseRenderer() par new Dummy(), alors que Dummy ne connaît pas du tout de méthode Hello !!!!!

    Qu'est-ce qui se passe? Pourquoi est ce que ça fonctionne encore?!

    D'une manière générale, est-ce que l'héritage est bien la technique à utiliser dans cette situation? Si non, que proposez-vous?

    Merci

    Cordialement

  2. #2
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    256
    Détails du profil
    Informations personnelles :
    Localisation : Etats-Unis

    Informations forums :
    Inscription : Juin 2002
    Messages : 256
    Par défaut
    En fait, je crois avoir compris.

    Lorsque je fais Pm->register( new Dummy() ), le compilateur cast automatique "vers le haut", en PluginsManager (car le prototype de ma fonction est "typedef void (*RegisterFc)(PluginsManagers* _pm)" ).
    Puis, une fois arrivé dans ma dll, il cast "vers le bas", en BaseRenderer. Cette dernière conversion ne posant aucun problème. Du coup, l'argument est bien initialisé et tout fonctionne.

    En revanche, c'est la conversion vers le haut qui peut potentiellement poser problème (ce que je voudrais, en fait).

    Donc comment pourrais-je faire pour que mon programme refuse de compiler ou au moins lance une exception si j'essaie de lancer register avec le mauvais type (pour la dll en question)?
    La seule solution que j'ai trouvé :
    - Ne plus faire dériver DummyRenderer et BaseRenderer de PluginsManager
    - changer l'argument dans le prototype de register en void*
    - caster dans la dll

    Ca "fonctionne" si les classes sont un peu évoluées et différentes (dans l'architecture). Par exemple, si ma méthode Hello tente d'écrire sur une variable que ne connait pas DummyRenderer, ca plante.
    Mais c'est vraiment pas propre... On pourrais pas avoir une petite exception quelque part qui permette de tout rattraper?
    Mieux, j'ai lu sur le forum qu'il y avait une technique utilisant l'héritage (recommandée par je-sais-plus-qui), mais je n'en sais pas plus...

    Un peu d'aide ne serait pas de refus.

    Merci

    Cordialement

  3. #3
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    256
    Détails du profil
    Informations personnelles :
    Localisation : Etats-Unis

    Informations forums :
    Inscription : Juin 2002
    Messages : 256
    Par défaut
    J'ai fini par trouver ce que je voulais faire. Pour la solution avec l'héritage, il fallait (du moins, ça à l'air de fonctionner) appeller register avec un vrai cast à la C++ :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Pm->register( dynamic_cast<Plugin*>(new BaseRenderer()) );
    (j'ai fait dériver de Plugin plutôt que PluginsManager, ça semble plus logique)
    et dans register downcaster avec dynamic_cast.

    Si j'appelle register avec BaseRenderer, ca passe, alors qu'avec dummyrenderer, ca jette une exception.

    Voilà. Qu'en pensez-vous?

    Merci

    cordialement

  4. #4
    Membre confirmé
    Inscrit en
    Juin 2008
    Messages
    85
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 85
    Par défaut
    Salut,

    Suite a ton poste j'ai fais des tests. J'ai fais trois classe :
    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
     
    class CTest
    {
    };
     
    class CTest2 : public CTest
    {
    };
     
    cclass CTest3 : public CTest
    {
    public:
    void CTest3::Affiche()
    {
    	cout<<"Bonjour";
    };
    };
     
    void main()
    {
    	CTest2 test2;
    	CTest3* ptr3;
     
    	ptr3 = (CTest3*) &test2;
    	ptr3->Affiche();
    }
    Il me semble qu'une variable ainsi qu'une classe est mis en mémoire uniquement lors de l'instanciation. Ce qui veut dire qu'une variable de type CTest2 est mis en mémoire lors de son instanciation (classe qui ne possède pas la méthode afficher). La ligne CTest3* ptr3; quand a elle ne déclare qu'une case mémoire pour y stocker une adresse (et donc pas une variable de type CTest3). Ce que je ne comprend pas c'est que l'on puisse faire un cast de la classe CTest2 (qui n'a pas de méthode affiche) vers la classe CTest3 et que lorsque l'on fasse afficher() "Bonjour" s'affiche dans la console. La méthode afficher() est mis en mémoire à quel moment? Un pointeur met il du code dans la zone pointée?

  5. #5
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

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

    Informations forums :
    Inscription : Février 2005
    Messages : 5 482
    Par défaut
    De toute façon, c'est une très mauvaise idée de partager des classes entre une Dll et un programme car cela entraîne un couplage fort entre ces deux composants logiciels.

  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
    Citation Envoyé par bacelar Voir le message
    De toute façon, c'est une très mauvaise idée de partager des classes entre une Dll et un programme car cela entraîne un couplage fort entre ces deux composants logiciels.
    ++

    Je rajouterais, puisque tu cast 'vers le bas' pourquoi offrir une interface avec PluginsManager? Autant utiliser directement BaseRenderer. Le compilateur te jetteras à ce moment.
    Sinon, un dynamic_cast devrait te retourner un NULL à l'exécution.

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

Discussions similaires

  1. [POO] Héritage et méthode non implémentée
    Par Keweed dans le forum C++
    Réponses: 10
    Dernier message: 08/12/2008, 15h14
  2. Réponses: 2
    Dernier message: 29/03/2007, 12h02
  3. [POO] Pointeur sur fonction membre et héritage
    Par MrDuChnok dans le forum C++
    Réponses: 9
    Dernier message: 20/07/2006, 17h19
  4. Réponses: 8
    Dernier message: 29/06/2006, 14h54
  5. Le linker ignore les fonctions non implémentées
    Par Rodrigue dans le forum C++Builder
    Réponses: 5
    Dernier message: 02/03/2005, 13h31

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