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 piles


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut Héritage et piles
    Bonjour,

    Je dois gérer un ensemble de classes toutes héritées de HFenetre qui regroupe toutes les fonctions utiles à cette gestion.

    J'ai donc fait une pile de pointeur de classe HFenetre.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    mon_pointeur = &classe_fille;
    //ou
    mon_pointeur = static_cast<HFenetre *>(&classe_fille);
    Mais quand j'utilise mon_pointeur->ma_fonction()
    Il exécute la fonction définie par HFenetre et non celle redéfinie par la classe fille.
    Je pourrais peut être soit faire plusieurs piles de pointeur de classe filles mais le nombre de ces classes n'est pas définie, si je dois me retrouver à 150 classes filles différentes...

    Avez-vous une idée pour utiliser la fonction de la classe fille au lieu de celle de la classe mère?

    Cordialement,
    Neckara

    EDIT : j'ai relu un tutoriel du SDZ que j'avais lu assez vite et j'ai appris le mot-clé virtual

  2. #2
    Membre émérite
    Avatar de Ekleog
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    448
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 448
    Par défaut
    Au passage, une std::stack de unique/shared_ptr pourrait être plus simple / efficace.

  3. #3
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    Je dois avouer que je ne connais pas ce dont tu me parles.

    J'ai trouvé 2/3 trucs pour shared_ptr mais pour unique je n'ai pas trouvé grand chose pour l'instant.

  4. #4
    Membre émérite
    Avatar de Ekleog
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    448
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 448
    Par défaut
    unique_ptr arrive avec c++11, donc si tu n'en as pas entendu parler c'est sûrement que tu n'as pas / ne connais pas cette dernière norme.
    Tu peux donc simplement te rabattre sur boost.shared_ptr, au prix d'un petit peu de performances.

  5. #5
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    es-tu déjà, simplement sur que la fonction redéfinie dans les classes filles existe et est déclarée virtuelle dans ta classe HFenetre, et que, en outre, les fonctions qui manipule des objets de type HFenetre les prennent sous la forme de références (éventuellement constantes) ou sous la forme de pointeurs

    Car, en théorie, tu peux fournir n'importe quel classe dérivée à toute fonction prenant en argument une référence (ou un pointeur) sur la classe de base et observer le polymorphisme.

    Mais cela ne fonctionne que si deux conditions sine qua non sont remplies:
    1. La fonction en question doit etre déclarée virtuelle dans la classe de base, autrement, sa redéfinition dans la classe dérivée occasionnera un "shadowing" de la fonction qui se trouve dans la classe de base, et, à l'inverse, ce sera la version définie pour la classe de base qui sera utilisée si l'objet passe pour etre du type de la classe de base
    2. Il faut travailler sur des références (éventuellement constante) ou sur des pointeurs vers la classe de base car, autrement, le compilateur "perd" une série d'informations relatives aux classes dérivées (à cause de la copie qui est effectuée lors du passage de l'argument), et ne peut donc travailler qu'avec ce que la classe de base connait
    Pour éviter ce genre de problème, l'idéal est, selon le cas:
    • d'interdire la copie et l'affectation des classes intervenant dans la hiérarchie
    • de faire en sorte que la classe de base soit une classe abstraite
    Il est en effet possible d'interdire la copie et l'affectation d'un type donné en déclarant (sans les implémenter) le constructeur par copie et l'opérateur d'affectation dans la visibilité privée.

    De cette manière, comme même les classe dérivées n'y ont pas accès, le compilateur t'insultera si tu te trouves dans une situation dans laquelle une copie ou une affectation s'effectue

    Il est à noter que la nouvelle norme (C++11) permet de déclarer certaines fonctions = delete ce qui a le meme effet

    Pour ce qui est des classes abstraites:

    Une classe est dite abstraite lorsqu'au moins une de ses fonctions membre est déclarée virtuelle pure (comprend: dont on ne donne pas d'implémentation), donc, sous la forme de virtual type_de_retour /* const &*/ foo() /* const*/ = 0;.

    Le compilateur ayant horreur du vide, il devient impossible de créer une instance de cette classe. C'est pour cette raison que l'on parle de classe abstraite

    Si, suite à une inattention de ta part, une instance de classe abstraite est créée (parce qu'une copie doit etre effectuée ou parce que tu essaye de créer directement une telle instance), le compilateur t'insultera en te disant que tu ne peux pas créer l'instance (et en précisant quelle fonction est virtuelle pure )

    Quelle que soit la solution choisie (ca peut etre les deux, car la justification que l'on donne à l'une et à l'autre est fondamentalement différente d'un point de vue conceptuel ) tu ne pourras plus avoir de fonction prenant un objet du type de la classe de base, mais tu pourras, en revanche, avoir des fonctions prenant une référence (éventuellement ocnstante) ou un pointeur sur un objet "passant pour etre" du type de la classe de base

    Il t'appartiendra donc de modifier le prototype de toutes les fonctions que le compilateur te signalera en conséquence
    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

  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
    Salut,

    Pour appeler une fonction définie dans la classe héritée à partir d'une référence ou d'un pointeur sur une classe de base, il faut que la fonction soit virtuelle.
    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
    #include <iostream>
     
    struct base
    {
       virtual void do_something() const
       {
          std::cout<<"base::do_something\n";
       }
       void do_something_else() const
       {
          std::cout<<"base::do_something_else\n";
       }
    };
     
    struct derived : base
    {
       virtual void do_something() const
       {
          std::cout<<"derived::do_something\n";
       }
       void do_something_else() const
       {
          std::cout<<"derived::do_something_else\n";
       }
    };
     
    void call(base const& rb)
    {
       rb.do_something();
       rb.do_something_else();
    }
     
    int main()
    {
       derived d;
       call(d);
       return 0;
    }
    donne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    derived::do_something
    base::do_something_else
    Note que la conversion de la classe dérivée vers la classe de base ne nécessite pas de conversion explicite : mon_pointeur = &classe_fille; alors que mon_pointeur = static_cast<HFenetre *>(&classe_fille);, inutile.

    L'allocation dynamique et l'utilisation des pointeurs intelligents est indépendante de l'héritage. Si l'héritage nécessite des pointeurs ou des références, aucun besoin que cela corresponde à une allocation dynamique.

    Un peu de lecture :
    Les fonctions virtuelles en C++

    Présentation des pointeurs intelligents en C++

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

Discussions similaires

  1. héritage liste chainée, pile chainée
    Par Onelove dans le forum Débuter
    Réponses: 2
    Dernier message: 16/09/2014, 12h54
  2. héritage pile FiFo Lifo
    Par jockerse dans le forum C++/CLI
    Réponses: 3
    Dernier message: 08/04/2014, 11h43
  3. La mémoire en Pmode et en Rmode - la pile
    Par le mage tophinus dans le forum Assembleur
    Réponses: 15
    Dernier message: 16/02/2003, 01h00
  4. [TASM] Déclarer le segment de pile
    Par cipher dans le forum x86 16-bits
    Réponses: 2
    Dernier message: 01/10/2002, 03h58
  5. Héritage entre Forms
    Par BarBal dans le forum Composants VCL
    Réponses: 7
    Dernier message: 29/08/2002, 17h44

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