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 :

Copie d’une classe fille avec instance de sa classe mère


Sujet :

C++

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2013
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2013
    Messages : 10
    Points : 13
    Points
    13
    Par défaut Copie d’une classe fille avec instance de sa classe mère
    Bonjour,

    Je m’amuse à créer une interface graphique en C++ :
    Pour ce faire, j’ai décidé d’utiliser une class de base nommé ‘Gadget’ qui est une classe mère.
    Les gadgets tels que ‘ImageBox’, ‘Button’, ‘GroupBox’, ‘Label’ … hérite donc de la class ‘Gadget’.

    Ensuite, il me suffit de mettre tous mes gadgets dans une liste unique de Gadget (‘ImageBox’, ‘Button’, ‘GroupBox’, ‘Label’ confondu).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::map<gadget_Id, Gadget*>   listGadget;
    Pour accéder à un membre d’ImageBox par exemple, je passe par l’instance de la class ‘Gadget’ se trouvant dans la liste des gadgets.
    Les fonctions membres virtuels de la class ‘Gadget’ accèdent à la classe fille sans connaitre son type (imageBox, Label, etc…)

    Cependant, Je bloque sur une amélioration que je voulais mettre en place.
    En effet, si je veux par exemple créer un clone d’une ‘ImageBox’.
    Je me suis dit aucun problème, je fais un constructeur de copie dans la classe ‘ImageBox’.

    Mais c’est là que cela se complique (voici le constructeur) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ImageBox(ImageBox* imgbox) ;
    Le problème est que je ne peux pas donner ImageBox à mon constructeur car mes gadgets sont stocker comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::map<gadget_Id, Gadget*>   listGadget;
    Le constructeur de mon ImageBox ne fonctionne pas bien évidement car il veux une instance d’ImageBox et non de ‘Gadget’ (qui est la classe mère).

    J’ai donc testé une autre solution de constructeur de copie mais cette fois avec la class mère en paramètre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ImageBox(Gadget* gadget) ;
    Et là évidement le constructeur fonctionne, mais je n’ai pas accès aux membres privé d’ImageBox

    Tous çà dans le but de créer des instances d’image afin de ne pas avoir plusieurs copie d’une même image en mémoire mais juste un pointeur vers une seule et unique image.

    Je suis obliger de créer des accesseurs virtuel dans la classe mère pour accéder aux variables membres privés de chaque classes filles ?
    Ou bien connaissez-vous une solution ?

  2. #2
    En attente de confirmation mail

    Profil pro
    Inscrit en
    Septembre 2013
    Messages
    639
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2013
    Messages : 639
    Points : 2 347
    Points
    2 347
    Par défaut
    Personnellement c'est quand j'ai commencé à me battre trop souvent contre ce genre de problème que j'ai laissé tombé cette soit-disant panacée qu'est la programmation objet.

    Du coup, je n'ai pas de solution à proposer... désolé...

  3. #3
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 483
    Points : 13 681
    Points
    13 681
    Billets dans le blog
    1
    Par défaut
    @CodeurPlusPlus : wooh ! belle intervention ! merci !



    @Golgrinet : deux petites choses avant de parler de ton vrai problème
    1. Plutôt que Gadget, utilise Widget, le nom universel pour ce genre de composants graphiques
    2. un constructeur par copie en C++ n'a généralement pas cette signature (voir http://en.cppreference.com/w/cpp/lan...py_constructor)


    Ici, il y a une méprise quant au but de la map. Elle te sert visiblement à faire de la gestion polymorphique, et donc à utiliser l'interface de la classe mère pour manipuler des instances de n'importe quelles classes filles. Par essence même, tu "perds" le type concret de tes objets, car tu t'en fiches. C'est souvent le but d'une gestion polymorphe. Si tu souhaites traiter uniquement des ImageBox, c'est bien que tu ne gères pas des Widgets (ou des Gadgets dans ton cas )

    Après, je vois venir ce que tu as fait : tu as utilises ton gadget_Id (une question au passage : qu'est ce que gadget_Id ?) pour récupérer un élément de ta map et tu sais qu'il est de type ImageBox. Pourquoi pas, même si a priori ce n'est pas très POO. Mais dans ce cas, et cela règlerait ton problème : pourquoi ne pas faire un cast ?

  4. #4
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 580
    Points : 7 712
    Points
    7 712
    Par défaut
    Le constructeur par copie a une forme bien précise et pour ce type d'objet, il est même fortement recommandé de désactiver la création automatique de celui-ci et de l'opérateur de copie
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        ImageBox( ImageBox const& ) = delete;
        ImageBox& operator=( ImageBox const& ) = delete;
    Si on veut créer un objet similaire qui récupérera la plupart des caractéristiques de son modèle, rien n'empêche de définir une fonction pour cela, et comme l'objet n'est utilisable que par pointeur ou référence, ça pourrait être par exemple std::shared_ptr<ImageBox> copie()const;.
    Si on souhaite créer un clone pour un Gadget quelconque, il suffit d'avoir déclaré une fonction virtuelle pure.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class Gadget {
        virtual std::shared_ptr<Gadget> copie()const = 0;
    };
    class ImageBox : public Gadget {
        std::shared_ptr<Gadget> copie()const override {
            auto idem = std::make_shared<ImageBox>();
            idem->x = this->x; // copier les membres...
            return idem; 
        }
    };

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2013
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2013
    Messages : 10
    Points : 13
    Points
    13
    Par défaut
    Merci pour vos réponses réactives çà fait plaisir.

    CodeurPlusPlus :

    Je pense que chaque langage à ces propres difficultés et ce que j’aime appeler sa propre philosophie.
    Mais a mon avis notre limite à résoudre un problème est notre imagination.

    Bktero :

    Widget au lieu de Gadget, oui pourquoi pas, il me semble que se nom est utilisé par d’autres librairies.
    Et oui, en effet, je n'ai pas donner la bonne syntaxe d'un constructeur désolé.

    En ce qui concerne la map c’est une autre histoire.
    En fait, je n’ai pas développé mon CDC car il est asseye volumineux mais dans l’interface je suis obliger de me servir de plusieurs structure de stockage adapter a ce que je voulais en faire (enfin je l’espère).

    La liste sous forme de map s’explique par le fait que les class ne sont pas disponible a l’utilisateur de la GUI, elles sont cachées.
    De se fait, les fonctions Create pour chaque gadget renvoie un ‘int’ qui sert a retrouver le gadget dans le map.
    Je ne voulais pas renvoyer l’instance de class brute car il y a une gestion des gadgets internes d’où le ‘gadget_Id’ qui n’est rien de plus qu’un typename unsigned int.
    Vous me direz, c’est lent comme méthode pour faire une modification sur un gadget…
    Et bien en fait pas tan que çà car j’utilise la philosophie OpenGL qui lock ces objets avant de les modifié.
    Map est donc utiliser pour stocker tous les gadgets créé par les fonctions create de la GUI.

    Mais j’ai d’autres listes, par exemple queue pour la gestion des évènements et une liste doublement chainé faite maison pour que mes gadgets possèdent aussi des enfants.
    Cette liste chainée est aussi utiliser par la fonction Draw qui dessine les gadgets a l’écran (parcouru de bas en haut, pour afficher en 1er les gadgets dessous)
    Et Update qui cette fois parcourt la liste de haute en bas (pour analyser si la souris passe sur un gadget au 1er plan car les gadgets ayant une interaction avec la souris sont placer en tête de liste).
    Mais là je m’égares, si tu veux plus de détail sur le fonctionnement interne je serais ravi de t’en dire plus.

    Dalfab:
    Je vais analyser ton code, il est intéressant.

  6. #6
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 128
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 128
    Points : 33 053
    Points
    33 053
    Billets dans le blog
    4
    Par défaut
    Salut,

    solution typique : une fonction virtual Mere* clone() const = 0;. T'ajoutes l'intelligence des pointeurs de ton choix ou pas autour de cette signature.

  7. #7
    Membre émérite Avatar de Astraya
    Homme Profil pro
    Consommateur de café
    Inscrit en
    Mai 2007
    Messages
    1 047
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Consommateur de café
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 1 047
    Points : 2 251
    Points
    2 251
    Par défaut
    + 1 pour virtual Mere* clone() const = 0;C'est un idiome courant que tout le monde comprends.
    Tu peux même allez plus loin en modifiant le type de retour ( Qui ne fait pas parti de la signature d'une function )
    Exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class Mere 
    {
    public:
        virtual Mere* clone() const = 0;
    };
     
    class Fille 
    {
    public:
        virtual Fille* clone() const override
        { 
            return new Fille(*this); // Appelle constructeur par copie de Fille 
        }
    };

  8. #8
    Membre expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    746
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2011
    Messages : 746
    Points : 3 667
    Points
    3 667
    Par défaut
    Attention avec le type de retour. Il ne fait pas partit des règles de surcharge, mais il fait bel est bien partit du prototype. Tu ne pourras pas retourner in int ou un Fille const * par exemple, car les types ne sont pas compatibles.

    Cette particularité s'appelle un type de retour covariant:
    - https://cpp.developpez.com/faq/cpp/?...tour-covariant
    - http://en.cppreference.com/w/cpp/language/virtual

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

Discussions similaires

  1. [Cache] Cacher les classes filles avec Ehcache
    Par etu_youssef dans le forum Hibernate
    Réponses: 2
    Dernier message: 22/02/2016, 02h14
  2. Réponses: 0
    Dernier message: 14/08/2013, 16h28
  3. Instance d'une classe fille à partir d'une classe mère
    Par Mathieu Salles dans le forum Débuter avec Java
    Réponses: 4
    Dernier message: 17/10/2012, 16h09
  4. Réponses: 1
    Dernier message: 08/01/2009, 11h23
  5. Declaré en classe de base, instancié en sous classe
    Par jobigoud dans le forum Langage
    Réponses: 3
    Dernier message: 14/11/2005, 10h55

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