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 :

polymorphisme et autre


Sujet :

C++

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2005
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Février 2005
    Messages : 3
    Par défaut polymorphisme et autre
    Bonjour à tous, j'ai un problème concernant le polymorphisme. Je vais essayé de simplifié le prob en vous donnant un simili code, qui est le suivant:

    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
    class A {
     
     virtual A:: methodeVirt(){
              ...
            }
     
     A::methodeA(){
            A monobjetA;
            ...
            monobjetA.methodeVirt();
            ...
            }
    }
     
     
    class B : public A {
     
    B:: methodeVirt(){
                 ...
             }
    }

    Mon problème est que lors de l'appel de la méthode A::methodeA(), l'objet "monobjetA" peut en fait être un objet de classe B (c'est possible grâce au code en "..."), et de ce fait, j'aimerais que ce soit la methodeVirt() de la classe B qui soit appelee dans ce cas. Or actuellement, systématiquement c'est la methodeVirt() de la classe A qui est appelée.

    Comment résoudre un tel problème? : ... Merci d'avance...


    [Balises CODE rajoutées par Loulou24, merci d'y penser à l'avenir]

  2. #2
    Membre confirmé
    Inscrit en
    Avril 2002
    Messages
    180
    Détails du profil
    Informations forums :
    Inscription : Avril 2002
    Messages : 180
    Par défaut
    si j'ai bien comprie ta question
    prenon ce bout de 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
     
    class A
    {
    public:
    	A(){cout<<"construeut A\n";}
    	~A(){cout<<"Destructeur A\n";}
     
    virtual Me(){cout<<"Class A\n";}
    };
     
    class B : public A
    {
    	public:
    	B(){cout<<"construeut B\n";}
    	~B(){cout<<"Destructeur B\n";}
     
    virtual Me(){cout<<"Class B\n";}
    };
     
    int main(int argc, char* argv[])
    {
    		A* a;
    		B* b;
    		A* ab;
    		cout<<"************************\n A* a=new A()\n";
    		a=new A();
    		a->Me();
     
    		cout<<"************************\n B* b=new B()\n";
    		b=new B();
    		b->Me();
     
    		cout<<"************************\n A* ab=new A()\n";
    		ab=new B();
    		ab->Me();
     
    	return 0;
    }

    A* ab=new B();
    initialise un object A avec le visage de B ainse l'apelle
    de ab->Me() aura comme sorti Classe B

  3. #3
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2004
    Messages
    47
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2004
    Messages : 47
    Par défaut
    l'objet "monobjetA" peut en fait être un objet de classe B (c'est possible grâce au code en "...")
    Le polymorphisme ne s'applique que sur les objets aux bouts d'un pointeur ou d'une référence. Donc si tu déclares ton objet de cette façon :
    monobjetA sera toujours de type A et tu ne pourras pas utiliser le polymorphisme

  4. #4
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2004
    Messages
    47
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2004
    Messages : 47
    Par défaut
    Citation Envoyé par philippe V
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    class A
    {
    public:
    	A(){cout<<"construeut A\n";}
    	~A(){cout<<"Destructeur A\n";}
     
    virtual Me(){cout<<"Class A\n";}
    };
    Attention, une classe suceptible d'être dérivé doit toujours déclaré sont destructeur comme virtuelle (dans ce cas c'est pas grâve car il ne fait rien, mais c'est bon d'avoir de bonne habitude).

  5. #5
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2005
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Février 2005
    Messages : 3
    Par défaut
    Il y a une chose qu'il ne faut pas oublier dans le problème que je décris, c'est que la méthode qui pose problème (MethodeA()) se situe DANS les méthodes de la classe mère (classe A) , et ce n'est pas la même chose que si j'avais voulu faire ce genre de manip dans un "main".... Déjà, parce que la classe fille (classe B) n'est pas définie encore et n'est pas complète si je ne fais que rajouter un "class B;" en entete du fichier de la classe A.

    Je vais essayé de changer la déclaration de monobjetA pour un type A* plutot que A comme vous l'avez conseillé, mais j'ai un doute sur le fait que ce soit la solution.... Je vous tiens au courant d'ici quelques minutes!


  6. #6
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2005
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Février 2005
    Messages : 3
    Par défaut
    Je viens d'essayer en utilisant plutot un pointeur "A* monobjetA" .... Ca n'a rien changé... l'appel de "MethodeVirt()" dans la MethodeA() appelle toujours celle de la classe A....


    Si vous avez d'autres idées, je suis toute ouïe !!!

  7. #7
    Membre confirmé
    Inscrit en
    Avril 2002
    Messages
    180
    Détails du profil
    Informations forums :
    Inscription : Avril 2002
    Messages : 180
    Par défaut
    Citation Envoyé par "CroustRyu
    Attention, une classe suceptible d'être dérivé doit toujours déclaré sont destructeur comme virtuelle (dans ce cas c'est pas grâve car il ne fait rien, mais c'est bon d'avoir de bonne habitude).
    tout afait d'acord


    Mon problème est que lors de l'appel de la méthode A::methodeA(), l'objet "monobjetA" peut en fait être un objet de classe B (c'est possible grâce au code en "..."), et de ce fait, j'aimerais que ce soit la methodeVirt() de la classe B qui soit appelee dans ce cas. Or actuellement, systématiquement c'est la methodeVirt() de la classe A qui est appelée.
    je ne suis pas sure de comprendre
    ca sera les methode de B qui seront appeler
    evideament l'object doit etre construit
    comment initialise-tu ton pointeur A ?????

  8. #8
    Membre éclairé
    Inscrit en
    Février 2005
    Messages
    53
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 53
    Par défaut
    Je pense que ce n'est pas possible car tu définis expressément monobjetA de type A donc la méthode de l'objet A est appelée. Si tu veux déclarer un objet de type B dans une méthode de A, il fait que tu déclares la classe B avant la méthode susnomée.

  9. #9
    Membre éclairé Avatar de Higestromm
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    516
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 516
    Par défaut
    Le polymorphisme ne s'applique que sur les objets aux bouts d'un pointeur ou d'une référence.
    Ah bon ? Je pensais que l'on ne pouvais appliquer le polymorphisme qu'a un pointeur ... je vais tester ca moi

  10. #10
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    134
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 134
    Par défaut
    Salut !
    je réveil un vieux sujet !


    Sinon j'ai un problème avec mes classes, et je pense que le polymorphisme est la clés ... seulement en c++ je le maitrise pas trop (et j'ai pas trop compris ce qu'est écrit dans la faq)

    en fait nous avons la classe QWidget ( librairie QT)
    j'ai ma classe MainWdg qui hérite de QWidget
    et ma classe GraphWdg qui hérite aussi de Qwidget

    ma classe MainWdg construit un grand nombre d'objet dont :
    l'objet suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    // dans MainWdg.h
    QWidget     * QWG_TabGraph;
     
    // dans MainWdg.cpp
    QWG_TabGraph     = new GraphWdw (TAB_Main,"Graphique");
    Donc mon objet QWG_TabGraph est un QWidget mais avec les méthode et les objets de ma classe GraphWdw. jusque là tout marche nikel.

    seulement quand je veux utiliser des méthodes que j'ai redefinis dans GraphWdw, il me dit
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    BRGraphWdw.h:60:7: warning: no newline at end of file
    BRMainWdw.cpp: In member function `void BRMainWdw::Xupdate()':
    BRMainWdw.cpp:160: error: 'class QWidget' has no member named 'initDraw'
    Donc je comprend bien, vu que mon objet est déclaré comme un Qvidget, il ne les trouve pas, mais pourtant elles sont là... vu que j'arrive à utilisé les constantes etc que j'ai défini dans cette classe...

    pour info, voilà comment j'ai appelé initDraw dans MainWdg.cpp :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    if ( interface == INTERFACE_GRAPH ) QWG_TabGraph->initDraw();
    (INTERFACE_GRAPH est une constante déclaré dans GraphWdg.h )


    bon bah voilà voilà ... j'espère avoir été clair si quelqu'un sait comment ça marche ou a un bon tuto
    Ah oui au fait : la question FINALE c'est : comment je m'y prend pour appeller ma fonction initDraw défini dans mon objet GraphWdg mais qui a été construit en tant que QWidget

    lol ... je risque d'embrouiller plus qu'autre chose donc je m'arrete...

  11. #11
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     ((GraphWdw*)QWG_TabGraph)->initDraw(); 
    ou
    reinterpret_cast<GraphWdw*>(QWG_TabGraph)->initDraw();
    permet de transtyper le pointeur QWG_TabGraph en un pointeur sur un GraphWdw.

  12. #12
    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 : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Ni l'un ni l'autre, pour le downcasting c'est dynamic_cast. Mais à utiliser avec précautions et dans des cas très précis, chercher les différents topics en parlant sur ce forum pour avoir plus de détails.

    A part ça, pourquoi ne pas déclarer ton widget comme étant un GraphWdw* tout simplement ?

  13. #13
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Ni l'un ni l'autre, pour le downcasting c'est dynamic_cast
    dynamic_cast ne peut pas marcher sauf si la classe de base possède des fonctions virtuelles. Si c'est le cas, je suis d'accord que dynamic_cast permet de vérifier que l'objet pointé est effectivement du bon type (dérivé) et que c'est une sécurité. (Personnellement c'est ce transtypage que je privilègie). Sinon teste les transtypages proposés (où il n'y a aucune garantie sur la réalité du type), je crois qu'ils sont corrects
    A part ça, pourquoi ne pas déclarer ton widget comme étant un GraphWdw* tout simplement ?
    OK. C'est la vraie question!

  14. #14
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 293
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 293
    Par défaut
    Citation Envoyé par CroustRyu
    Attention, une classe suceptible d'être dérivé doit toujours déclaré sont destructeur comme virtuelle (dans ce cas c'est pas grâve car il ne fait rien, mais c'est bon d'avoir de bonne habitude).
    Non. La nécessité n'est vraie seulement si ses objets sont susceptibles d'être détruits polymorphiquement.


    Pour reinterpret_cast, il y a aussi des cas où il ne machera pas. Si les fonctions ne sont pas virtuelles et que l'on essaie de faire de genre d'horreurs, on a le choix entre :
    - erreur de design, on rajoute les virtual qui manquent
    - on encapsule dans des adaptateurs qui vont réintroduire (via délégation) le polymorphisme d'héritage oublié en chemin. -- cela me fait penser à boost.interface que j'ai croisé par hasard aujourd'hui ; c'est sur le wiki.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  15. #15
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    134
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 134
    Par défaut
    A part ça, pourquoi ne pas déclarer ton widget comme étant un GraphWdw* tout simplement ?
    parceque :
    MainWidget est la classe qui définit ma fenetre principale, et à l'intérieur de ce widget il y 'en a d'autre dont notament BRGraphWdg, mais la fonction QT qui intègre ce widget à ma fenetre principal nécessite que ce soit un QWidget .
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    // Dans le .h
       QTabWidget  * TAB_Main; 
       QWidget     * QWG_TabGraph;
       QWidget     * QWG_TabZoom;
     
    // Dans le .cpp
       TAB_Main         = new QTabWidget (this,"");
       QWG_TabGraph     = new BRGraphWdw (TAB_Main,"Graphique");
       QWG_TabZoom      = new BRGraphWdw (TAB_Main,"Zoom");
     
       TAB_Main         -> insertTab( QWG_TabGraph, QString("Mode Graphique") );
       TAB_Main         -> insertTab( QWG_TabZoom, QString("Fiche des entitées") );
    Je ne pense pas qu'on puisse faire autrement. Si je déclare mes QWG_... en BRGraphWdw il va comprendre que ce sont des QWidget quand je ferais QTabWidget::insertTab ( QWidget * child, const QString & label, int index = -1 )
    ?


    Sinon teste les transtypages proposés (où il n'y a aucune garantie sur la réalité du type)
    OK. merci encore ^^ ... ça a l'air ed marcher.

    j'ai fait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ((BRGraphWdw*) QWG_TabGraph )->initDraw();
    Merci de votre aide.

  16. #16
    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 : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    La conversion Derivee* -> Mere* est possible et se fait implicitement. Donc bien sûr que tu peux déclarer tes pointeurs avec leur type réel

Discussions similaires

  1. Polymorphisme ou transtypage ou autres?
    Par totoche dans le forum Langage
    Réponses: 2
    Dernier message: 01/11/2007, 12h17
  2. [langage] Comparer Perl avec d'autres langages comme C ?
    Par Anonymous dans le forum Langage
    Réponses: 3
    Dernier message: 10/08/2002, 23h52
  3. Réponses: 2
    Dernier message: 10/07/2002, 11h51
  4. Réponses: 2
    Dernier message: 21/05/2002, 10h25
  5. Réponses: 3
    Dernier message: 09/05/2002, 01h39

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