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

Langage C++ Discussion :

Attribut classe mère initialisé dans dérivées


Sujet :

Langage C++

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 366
    Points : 116
    Points
    116
    Par défaut Attribut classe mère initialisé dans dérivées
    Bonjour a tous,

    J'ai un petit probleme, une classe de Base dont dérivent X objets.
    Chaque objet possede une map<string, string> propre a lui meme.

    Par contre l'initialisation de cette map et son utilisation est commune a tout les objets. Je voulais donc mettre tout les traitements de cette map dans ma classe de base.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    class Base
    {
    protected:
        static std::map<std::string, std::string> _dicoParam;
        void initDico( void ); // Init commune du dico
    };
    class Fille: public Base
    {
    ...
    }
    Et dans le cpp de mes filles
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    std::map<std::string, std::string> Fille::_dicoParam= {{"A","B"},{"C","D"}}
    Mais l'initialisation d'un membre static ne peut pas etre faite dans les derivees.
    Y a t il un moyen de faire quelque chose dans cet esprit ?

    Merci d'avance

  2. #2
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 611
    Points
    30 611
    Par défaut
    Salut,

    Attends, j'aimerais être sur de comprendre...

    Ton membre _dicoParam doit il etre rempli une bonne fois pour toute, indépendamment de l'instance de la classe fille utilisée, ou veux tu simplement que chaque classe fille présente une fonction initDico de manière à pouvoir profiter du polymorphisme (ce qui fait que chaque classe dérivée pourra initialiser le membre avec ses propres données).

    Dans le premier cas, tu fais bien d'utiliser une variable statique, mais c'est un membre de la classe parent, ce qui fait que tu devrait "simplement" remplacer Fille::_dicoParam par Base::_dicoParam

    Dans le deuxième cas, la classe Base n'a, a priori, pas besoin de disposer du membre _dicoParam ou, en tous cas, pas sous une forme statique (et si elle dispose de dicoParam, il faudra sans doute la placer dans l'accessibilité protégée, ce qui, personnellement, me dérange quand meme un peu ).

    Par contre, il faudra déclarer la fonction initDico comme étant virtuelle (éventuellement virtuelle pure, si Base ne dispose pas du membre _dicoParam ), pour pouvoir réimplémenter son comportement dans les classes dérivées.

    Ceci dit, ce n'est qu'un détail, mais l'underscore " _ " comme préfix est réservé à l'implémentation du compilateur.

    Si tu veux distinguer les membres d'une classe, tu devrais décider de le placer en suffixe (sous la forme de dicoParam_ ), par exemple
    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

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 366
    Points : 116
    Points
    116
    Par défaut
    Bonjour et merci pour ta reponse.

    C'est la deuxieme solution du coup oui je n'y ai pas pensé mais ca ne pourra pas marcher car chaque instance filleA filleB a son propre paramDico.
    En fait mon initialisation du dico est dependant de ma classe fille, par contre l'utilisation qui en est faite est commune.

    Du coup je me suis pris la tete pour rien,
    Je declare mon Dico dans ma classe mere, avec une methode traiteDico commune et une methode initDico virtuelle.
    Chaque fille l'implemente en fonction de ses données.
    Si je ne declare pas Dico dans la mere, le traiteDico ne pourra pas etre commun (ou je me trompe, y a t il une solution ?)

    C'est l'habitude de vouloir tout initialiser via vecteur d'init que j'ai zappe une simple methode d'init..

  4. #4
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par sone47 Voir le message
    Si je ne declare pas Dico dans la mere, le traiteDico ne pourra pas etre commun (ou je me trompe, y a t il une solution ?)
    C'est bien ça. Il y aurait des solutions, mais ça n'aurait pas vraiment de sens. C'est la logique de l'héritage public: ce que possède la classe de base est également possédé par toutes ses classes dérivées, mais pas l'inverse.
    Si tu veux mettre des objets que dans les classes dérivées, alors ça n'a pas de sens de vouloir manipuler ces objets à un niveau supérieur. Tu peux déclarer les contrats (ou le protocole, ou comme vous voudrez l'appeler) au niveau supérieur, mais pas l'implémentation.

    Sinon, bien souvent la nécessité d'une fonction Init cache une erreur de conception. Je te propose de lire cette faq.
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 366
    Points : 116
    Points
    116
    Par défaut
    Ok merci,
    Je suis parti sur une piste ou le constructeur de chaque instance fille fait appel à initDico().
    Mais j'ai du mal a voir mon problème de conception, ce que je pourrais faire c'est ne rien mettre dans la mère et tout déporter dans les classe dérivées mais si je change un traitement du dico je vais devoir tout me frapper toutes les modifs pour chaque fille...
    Je pensais que ça simplifiait justement le code.

  6. #6
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    Appeler la fonction Init dans le constructeur est une bonne solution, tant que cette fonction Init est privée (ou protégée).

    Si cette initialisation est différente selon chaque classe fille, un simple template method suffit:
    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: 
       Mere() { Init(); } // constructeur qui appelle Init()
     
    protected:
       virtual void Init() = 0;
    };
     
    class Fille : public Mere
    {
    private:
       void Init() { /* l'implémentation ici */ }
    };
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 366
    Points : 116
    Points
    116
    Par défaut
    Ok merci pour ces précisions,
    C'est exactement ce que j'ai fais.
    Question bete mais c'est quoi un "template method"?

  8. #8
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    template method (ou patron de méthode) est un design pattern (ou patron de conception). Ce sont des schémas qui définissent un agencement de classes dans le but de résoudre des problèmes courants lorsqu'on programme en utilisant des objets (programmation orientée objet, poo). Jette un coup d'oeil ici, c'est le template method. Ca peut paraître compliqué à première vue, mais en fait c'est très simple et très utile.
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  9. #9
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 113
    Points : 32 958
    Points
    32 958
    Billets dans le blog
    4
    Par défaut
    Malheureusement ceci est impossible.
    Mere est construit avant Fille, et Mere n'a aucune connaissance de Fille.
    L'appel d'une méthode virtuelle dans le constructeur apelle son implémentation dans la classe actuelle (ou une classe mère, en aucun cas dans sa classe Fille).

    Si ce genre de procédés est nécessaire, il faut faire l'initialisation en 2 temps:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Fille* pFille = new Fille;
    pFille->Init();
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  10. #10
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    oops en effet, tu as raison
    En fait, je suis justement en train de travailler sur une architecture qui permet ça, mais en passant par du p_impl et du clone(); du coup j'avais oublié que ce n'était pas si direct.

    D'ailleurs, un peu de bonne lecture
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

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

Discussions similaires

  1. Réponses: 5
    Dernier message: 08/04/2013, 14h52
  2. Réponses: 9
    Dernier message: 28/01/2013, 11h42
  3. Réponses: 4
    Dernier message: 14/12/2011, 16h58
  4. Réponses: 7
    Dernier message: 05/04/2011, 18h19
  5. attribut class dans html:link
    Par gloglo dans le forum Struts 1
    Réponses: 2
    Dernier message: 20/12/2006, 12h57

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