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 :

[Heritage de classes] - acceder à une fonction


Sujet :

C++

  1. #1
    Membre éclairé
    Avatar de buzzkaido
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2004
    Messages
    821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2004
    Messages : 821
    Points : 734
    Points
    734
    Par défaut [Heritage de classes] - acceder à une fonction
    Bonjour,

    Voila, j'ai deux classes :
    - cObjet : mon objet
    - iEcouteurEvenement : un ecouteur d'evenements (par ex : la souris)

    Lorsque je construit un nouvel objet qui doit ecouter les evenements, par exemple un bouton, je construit une nouvelle classe :

    cBouton, qui hérite de cObjet et de iEcouteurEvenement

    Mon probleme :

    Dans cObjet, j'ai une variable booléene : estEcouteurEvenement qui vaut false par défaut.

    Lorsque je crée un cBouton, je voudrais que estEcouteurEvenement soit égal à true de façon automatique.

    Alors j'ai pensé à ça : dans le constructeur de iEcouteurEvenement, mettre estEcouteurEvenement à true.

    Sauf que estEcouteurEvenement est membre de cObjet.

    Vu que cBouton hérite des deux (cObjet et iEcouteurEvenement) doit bien y avoir un moyen de mettre estEcouteurEvenement à true dans la construction de iEcouteurEvenement ?

    (je pourrais toujours le faire dans le constructeur de cBouton, mais je perd mon automatisme)

    Merci !

  2. #2
    Membre expert
    Avatar de hiko-seijuro
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    2 011
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 2 011
    Points : 3 065
    Points
    3 065
    Par défaut
    euh tu as essayé ca :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    cObjet::estEcouteurEvenement = true;
    mais je doute de la validité de ta conception .... :s

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

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    A mon avis ta conception mériterait d'être revue, je doute qu'il soit nécessaire de faire ce que tu fais.

    Pourquoi souhaites-tu garder un booléen indiquant si l'objet dérive de iEcouteurEvenement ?

  4. #4
    Membre éclairé
    Avatar de buzzkaido
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2004
    Messages
    821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2004
    Messages : 821
    Points : 734
    Points
    734
    Par défaut
    Ah, effectivement, je n'ai pas essayé...

    Je doute aussi de la validité de ma conception, mais c'est en phase de tests... pour valider, justement !

    En fait, pour l'instant j'ai ça, qui est validé :

    - Je crée un objet (bouton = new cBouton)
    - j'ajoute cet objet dans un conteneur (conteneur->ajouteObjet(bouton))

    Mais je voudrais que si mon objet (ici cBouton) implémente iEcouteurEvenement, alors lorsque je fait conteneur->ajouteObjet, le conteneur ajoute l'objet non seulement dans sa liste "d'enfants", mais aussi dans sa liste d'ecouteurs, de facon automatique.

    Donc j'ai pensé mettre un booléen ::estEcouteurEvenement dans chaque objet, qui indique si il doit etre ajouté à la liste d'ecouteurs ou non, et que ce booléen soit mis à true lors de la construction de iEcouteurEvenement.

    Comme ça :
    - un objet qui ne l'implemente pas a ce booléen à false est n'est pas ajouté à la liste d'ecouteurs
    - un objet qui l'implemente, lors de sa construction, le booleéen est mis à true, et lors de l'ajout au parent, il est aussi ajouté à la liste d'ecouteurs

    Evidemmenent, si il y a mieux, je suis prenneur !

  5. #5
    Expert éminent

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Points : 7 618
    Points
    7 618
    Billets dans le blog
    3
    Par défaut
    Si tu compiles avec le mode RTTI (runtime type information) de ton compilateur, il suffit de 'caster' le cObject en iEcouteurEvenement . Si le résultat est null, alors le cObject implémente pas, sinon, il implémente.

    Si tu compiles sans RTTI... alors:
    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
     
    class cObject
    {
       ...
     
       virtual iEcouteurEvement*   getEcouteur(void) const
       { return 0; }
     
    };
     
     
     
    class cButton : public cObject, iEcouteurEvenement
    {
        ....
     
       virtual iEcouteurEvement*   getEcouteur(void) const
       { return (iEcouteurEvenement*)this; }
    }
     
     
     
     
    conteneur::ajouteObject(const cObject* pObj)
    {
         .....
         iEcouteurEvenement* pEcouteur = pObj->getEcouteur();
         if (pEcouteur)
             ajouteEcouteur(pEcouteur);
    }
    Bon, je me suis certainement mélangé les pinceaux entre anglais et français (c'est dingue le mal que j'ai à mettre du français dans du code !)

    Mais on est obligé de demander l'interface iEcouteurEvenement à l'objet, parceque l'addresse mémoire de l'interface (celle de la table virtuelle de l'interface) ne correspond pas à l'addresse mémoire de l'objet (celle de la table virtuelle de l'objet). Donc un simple cast (iEcouteurEvenement*) ne fonctionne pas.

  6. #6
    Membre éclairé
    Avatar de buzzkaido
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2004
    Messages
    821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2004
    Messages : 821
    Points : 734
    Points
    734
    Par défaut
    Je connaissait pas le RTTI...

    Et sinon, sans RTTI, effectivement, c'est pas con comme methode !

    Merci !

    Euh... au passage, tu pourrait me donner plus d'infos sur le RTTI ?
    Ou c'est que ça se regle comme option ?
    En terme de performances, je suppose que c'est un peu gourmand, non ?

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

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Pas besoin de créer une fonction virtuelle pour vérifier le type réel d'un objet, le RTTI permet justement de le faire directement via dynamic_cast (voir FAQ)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    conteneur::ajouteObject(const cObject* pObj)
    {
         .....
         iEcouteurEvenement* pEcouteur = dynamic_cast<iEcouteurEvenement*>(pObj);
         if (pEcouteur)
             ajouteEcouteur(pEcouteur);
    }
    Mais bon, je pense que ton design pourrait être amélioré pour éviter ce genre de "bidouille".

    PS : le cast (iEcouteurEvenement*)this est fortement déconseillé dans ce contexte, dans certaines circonstances il ne renverra pas ce que l'on attend

  8. #8
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 382
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 382
    Points : 41 590
    Points
    41 590
    Par défaut
    L'exemple de nicroman n'utilise pas la RTTI, d'ailleurs. Juste une simple fonction virtuelle...

    Et pour le code de Laurent Gomila qui lui, utilise la RTTI, je rappelle/précise que ça ne marche que si la classe contient au moins une fonction virtuelle (qui peut être le destructeur). Enfin, ce doit être dans la FAQ...

  9. #9
    Expert éminent

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Points : 7 618
    Points
    7 618
    Billets dans le blog
    3
    Par défaut
    Dans les options de compilateur, il y a normalement un flag pour spécifier si on veut utiliser le RTTI (RunTime Type Information) ou non.

    Sans RTTI point de dynamic_cast<>.
    Le RTTI introduit pas mal d'overhead au démarrage (mais est-ce vraiment important ?), grossi quelque peu le code, et le dynamic-cast est assez long à effectuer, mais quel confort pour la gestion des interfaces !!!

    Entre parenthèse, encore une fois, tout dépend de ce qu'on veut faire...
    Aller vite, ou aller surement

    Si la vitesse n'est pas à priviligier... alors le dynamic-cast est vraiment la meilleure solution !

  10. #10
    Membre éclairé
    Avatar de buzzkaido
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2004
    Messages
    821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2004
    Messages : 821
    Points : 734
    Points
    734
    Par défaut
    Je reveille ce vieux sujet à cause d'une interrogation sur les cast...

    Lorsque je fais un cast comme ça :

    nouvelleVariable = (nouveauType) variable;

    De quel type de cast s'agit-il vraiment ?

    Merci !

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

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Il s'agit juste d'un cast de type C.

    Il peut prendre la place de n'importe lequel des 4 casts du C++, excepté dynamic_cast dans certains cas.

  12. #12
    Membre éclairé
    Avatar de buzzkaido
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2004
    Messages
    821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2004
    Messages : 821
    Points : 734
    Points
    734
    Par défaut
    Ok !

    Et, euh, y-a-t-il une possibilité d'empecher le dynamic_cast ?

    (pour des raisons de perfs)

    Ou est-ce qu'il suffit de desactiver le RTTI ?

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

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Si tu veux "empêcher" les dynamic_cast il n'y a pas 50 solutions, évite d'en écrire.
    Je sais que sur certains compilateurs, utiliser dynamic_cast avec le RTTI désactivé provoque une erreur, mais je ne sais pas si c'est un comportement standard.

    Dans ce sens, boost::polymorphic_downcast est pas mal : en mode debug il fait un dynamic_cast et lève une exception lorsqu'il échoue ; en mode release il fait un simple static_cast.

  14. #14
    Membre éclairé
    Avatar de buzzkaido
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2004
    Messages
    821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2004
    Messages : 821
    Points : 734
    Points
    734
    Par défaut
    Merci !

    Et hop, résolu !

  15. #15
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par Laurent Gomila
    Dans ce sens, boost::polymorphic_downcast est pas mal : en mode debug il fait un dynamic_cast et lève une exception lorsqu'il échoue ; en mode release il fait un simple static_cast.
    Ce qui ne couvre qu'une partie des cas d'utilisation. On peut faire des dynamic_cast vers un type sans rapport avec le type statique de l'objet (utile avec les interfaces).

  16. #16
    Membre éclairé
    Avatar de buzzkaido
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2004
    Messages
    821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2004
    Messages : 821
    Points : 734
    Points
    734
    Par défaut
    Ouais, ben finalement, pas tant résolu que ça...

    Y'aurait moyen d'avoir quelques precisions, je ne suis pas très familier des différents types de cast...

  17. #17
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 382
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 382
    Points : 41 590
    Points
    41 590
    Par défaut
    L'utilisation évoquée par Jean-Marc.Bourguet est ce qu'on appelle un Cross-cast (voir FAQ).
    Utile si un type implémente plusieurs interfaces et qu'on veut passer de l'une à l'autre: pour ceux qui touchent à COM/OLE, ça donne un équivalent de QueryInterface().

    Comme son nom l'indique, le polymorphic_downcast ne supporte pas le cross-cast: Seulement le down-cast, qui est un cast d'une classe de base en une classe dérivée.

  18. #18
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut

  19. #19
    Membre éclairé
    Avatar de buzzkaido
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2004
    Messages
    821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2004
    Messages : 821
    Points : 734
    Points
    734
    Par défaut
    Ben oui, FAQ...

    Je l'ai déjà lu, mais certains trucs m'échappe... surement le manque de pratique !

    Promis, je la relit ce week-end !

  20. #20
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Clique dessus, je suis un peu plus precis que cela.

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 17/04/2007, 18h14
  2. [.NET2.0][C#]Passage type de classe dans une fonction
    Par SLE dans le forum Windows Forms
    Réponses: 4
    Dernier message: 06/06/2006, 16h48
  3. [AS2] Atteindre attribut d'une classe depuis une fonction interne a la classe
    Par Demco dans le forum ActionScript 1 & ActionScript 2
    Réponses: 6
    Dernier message: 18/04/2006, 22h03
  4. [class] Ajouter class devant une fonction
    Par Pedro dans le forum Langage
    Réponses: 12
    Dernier message: 07/03/2005, 14h11
  5. Réponses: 4
    Dernier message: 17/03/2004, 18h24

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