Précédent   Forum du club des développeurs et IT Pro > C et C++ > C++ > Langage
Langage Langage C++, Programmation Orientée Objet, Templates, etc. Avant de poster : FAQ C++
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 07/01/2013, 12h16   #1
sone47
Membre régulier
 
Inscription : novembre 2006
Messages : 349
Détails du profil
Informations forums :
Inscription : novembre 2006
Messages : 349
Points : 79
Points : 79
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 :
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 :
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
sone47 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/01/2013, 12h32   #2
koala01
Modérateur
 
Avatar de koala01
 
Philippe Dunski
Inscription : octobre 2004
Messages : 8 626
Détails du profil
Informations personnelles :
Nom : Philippe Dunski
Âge : 41

Informations forums :
Inscription : octobre 2004
Messages : 8 626
Points : 13 346
Points : 13 346
Envoyer un message via MSN à koala01 Envoyer un message via Skype™ à koala01
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
je ne répondrai à aucune question technique par E-mail, message visiteur ou message privé
Vous avez obtenu votre réponse pensez au bouton en bas de page
koala01 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/01/2013, 13h25   #3
sone47
Membre régulier
 
Inscription : novembre 2006
Messages : 349
Détails du profil
Informations forums :
Inscription : novembre 2006
Messages : 349
Points : 79
Points : 79
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..
sone47 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/01/2013, 14h09   #4
r0d
Expert Confirmé Sénior
 
Inscription : août 2004
Messages : 3 673
Détails du profil
Informations personnelles :
Localisation : Belgique

Informations forums :
Inscription : août 2004
Messages : 3 673
Points : 4 436
Points : 4 436
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.
r0d est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/01/2013, 14h33   #5
sone47
Membre régulier
 
Inscription : novembre 2006
Messages : 349
Détails du profil
Informations forums :
Inscription : novembre 2006
Messages : 349
Points : 79
Points : 79
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.
sone47 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/01/2013, 15h06   #6
r0d
Expert Confirmé Sénior
 
Inscription : août 2004
Messages : 3 673
Détails du profil
Informations personnelles :
Localisation : Belgique

Informations forums :
Inscription : août 2004
Messages : 3 673
Points : 4 436
Points : 4 436
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 :
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 */ }
};
r0d est déconnecté   Envoyer un message privé Réponse avec citation 01
Vieux 07/01/2013, 15h58   #7
sone47
Membre régulier
 
Inscription : novembre 2006
Messages : 349
Détails du profil
Informations forums :
Inscription : novembre 2006
Messages : 349
Points : 79
Points : 79
Ok merci pour ces précisions,
C'est exactement ce que j'ai fais.
Question bete mais c'est quoi un "template method"?
sone47 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/01/2013, 16h08   #8
r0d
Expert Confirmé Sénior
 
Inscription : août 2004
Messages : 3 673
Détails du profil
Informations personnelles :
Localisation : Belgique

Informations forums :
Inscription : août 2004
Messages : 3 673
Points : 4 436
Points : 4 436
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.
r0d est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 07/01/2013, 16h12   #9
Bousk
Modérateur
 
Homme Cyrille
Network programmer
Inscription : juin 2010
Messages : 1 553
Détails du profil
Informations personnelles :
Nom : Homme Cyrille
Âge : 25
Localisation : France

Informations professionnelles :
Activité : Network programmer

Informations forums :
Inscription : juin 2010
Messages : 1 553
Points : 4 109
Points : 4 109
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 :
1
2
Fille* pFille = new Fille;
pFille->Init();
Bousk est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 07/01/2013, 16h36   #10
r0d
Expert Confirmé Sénior
 
Inscription : août 2004
Messages : 3 673
Détails du profil
Informations personnelles :
Localisation : Belgique

Informations forums :
Inscription : août 2004
Messages : 3 673
Points : 4 436
Points : 4 436
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
r0d est déconnecté   Envoyer un message privé Réponse avec citation 10
Réponse Cette discussion est résolue.
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 22h21.


 
 
 
 
Partenaires

Hébergement Web