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 :

question a propos d'héritage


Sujet :

C++

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 6
    Par défaut question a propos d'héritage
    je dispose d'une classe message
    dont héritent les classes messages1, message2, message3

    j'ai un objet message * m

    que j'instancie suivant la valeur d'un entier
    si i = 1 : m = new Message1
    si i = 2 : m = new Message2
    ...

    Je cherche un moyen d'automatiser cette instanciation.

    par exemple en déclarant les différentes classes message1 message2 dans un tableau
    et que mon programme crée un objet message1 quand i = 1 sans que cela soit explicitement ecrit dans le code.
    Le but étant lors de l'ajout d'un message_i de n'avoir qu'a compléter ce tableau et
    pas avoir a rajouter tous les endroits ou l'objet peut etre instancié dans le code.

    est ce faisable ? si oui, comment ?
    merci pour vos pistes.

  2. #2
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    Juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 1 309
    Par défaut
    Si i est connu seulement à l'execution, il va faloir forcément passer par un truc un peu sale comme tu as.

    Si il est connu a la compilation, tu peux passer par un template : Message<i>

  3. #3
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 327
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 327
    Billets dans le blog
    2
    Par défaut
    Bonjour,

    je ne connais pas la raison pour laquelle tu as cet héritage, je ne peux donc pas être trés précis dans ma réponse. Mais une solution est possible, c'est, comme le propose NiarmorH, de transformer ta classe message en classe template.

    Si cette solution n'est pas possible, il y d'autres solutions qui consistent à utilisent l'héritage autrement. Je pense notamment au DP template method.

    A voir selon ce que tu souhaites faire exactement avec cette classe message.

  4. #4
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    Juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 1 309
    Par défaut
    Je doute très très fort que le template soit la solution à retenir ici.

    Je pense que ce dont tu as besoin est une fabrique ou un monteur.

  5. #5
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 327
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 327
    Billets dans le blog
    2
    Par défaut
    Bah, si toutes les classes filles ont la même interface (j'entend par là l'ensemble des méthodes publiques), pourquoi pas?

  6. #6
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Par défaut
    La fabrique est ici toutes bien venu.
    En effet, elle permet de crée des d'objets dérivant d'une même classe de facon transparent en se basant sur des clé de nimporte quel type pour instancier tes objets.
    Voici un exemple de fabrique basé sur les templates et une création d'objet via prototypage:
    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
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    #include <iostream>
    #include <map>
    #include <iterator>
    #include <string>
     
    using namespace std;
     
    //la classe prototype
    template <class T> class Prototype
    {
    	public:
    	virtual ~Prototype(){}	
    	virtual T* Clone() const =0 ;
    };
     
    //l'interface "Figure" 
    class Figure : public  Prototype<Figure>
    {
    	public: 
    	virtual void SeDessiner()=0;
    };
     
    class Carre : public Figure 
    {
    public:
    	Figure* Clone() const ;
    	void SeDessiner();
    };
     
    class Cercle : public Figure 
    {
    public:
    	Figure* Clone() const ;
    	void SeDessiner();
    };
     
    //La fabrique a proprement parler
    template <class Object,class Key=string> class Factory
    {
    std::map<Key,Object*> m_map;
    public:
     
    	//La fonction qui va créer les objets
    	Object* Create(const Key& key) const ;
     
    	//Celle qui associe clé <=> prototype
    	void Register(Key key,Object* obj);
    };
     
     
     
    Figure* Carre::Clone() const 
    {
     return new Carre(*this);
    }
     
    void Carre::SeDessiner()
    {
    cout<<"Je suis un Carre"<<endl;
    }
     
     
    Figure* Cercle::Clone() const 
    { 
    	return new Cercle(*this);
    }
     
    void Cercle::SeDessiner()
    {
    	cout<<"Je suis un Cercle"<<endl;
    }
     
     
     
    template <class Object,class Key> void Factory<Object,Key>::Register(Key key,Object* obj)
    {
    //si la clé n'est pas déja présente
    		if(m_map.find(key)==m_map.end())
          	{
    			//on ajoute l'objet dans la map
    			m_map[key]=obj;
    		}
    //on pourrai détruire obj mais cette tache ne revient pas à la Register
    }
     
    template <class Object,class Key> Object* Factory<Object,Key>::Create (const Key& key) const 
    {
    		Object* tmp=0;
     
    		typename std::map<Key, Object*>::const_iterator it=m_map.find(key);
     
    		//si l'itérateur ne vaut pas map.end(),cela signifique que la clé à été trouvé     
    		if(it!=m_map.end())
    		{
    			//donc on clone l'objet
    	      	tmp=((*it).second)->Clone();
          	}
    //on pourrai lancer une exeption au besoin
    		return tmp;
    }
     
     
     
    int main(void)
    {
     Factory<Figure> fac;
     
     fac.Register("Carre",new Carre);
     fac.Register("Cercle",new Cercle);
     
      Figure *c=fac.Create("Cercle");
      Figure *ca=fac.Create("Carre");
     
      c->SeDessiner();
      ca->SeDessiner();
     
      delete c;
      delete ca;
     
      return 0;
    }
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  7. #7
    Alp
    Alp est déconnecté
    Expert confirmé

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    En effet, le Design Pattern Factory est ici ce qu'il faut.
    J'allais le suggérer avant de lire ton message David

  8. #8
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    Juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 1 309
    Par défaut
    Citation Envoyé par r0d Voir le message
    Bah, si toutes les classes filles ont la même interface (j'entend par là l'ensemble des méthodes publiques), pourquoi pas?
    Ca n'apportera rien si i n'est connu qu'à l'éxécution.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    IMessage *
    GetMessage( int i )
    {
      return new Message<i>();
    };
    Ne compilera pas.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    template <int i>
    Message<i>
    GetMessage<i>()
    {
      return Message<i>();
    };
    Celui-ci marcherait.

    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
    enum MessageList
    {
      ALERT = 0,
      ERROR = 1,
      INFO   = 3
    };
     
    int main()
    {
      MessageVector vec;
      vec.push_back( new Message<MessageList::ALERT>() );
      vec.push_back( new Message<MessageList::ERROR>() );
      vec.push_back( new Message<MessageList::INFO>() );
      for_each( vec.begin(), vec.end(), display() );
    }
    Marcherait aussi, mais ce qu'il cherche à faire est factoriser la création avec un i à l'éxécution et ça c'est pas faisable.

  9. #9
    Alp
    Alp est déconnecté
    Expert confirmé

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    Oui, en effet NiamorH. Et dans ce cas, la méthode la plus "simple" est la factory...

  10. #10
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    Juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 1 309
    Par défaut
    Voilà, je pense aussi.

  11. #11
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 327
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 327
    Billets dans le blog
    2
    Par défaut
    Oui pardon, je me suis mal exprimé. En fait, ce que je voulais dire, c'est qu'il n'a peut-être pas besoin de faire ce if (ou switch).

    <mode extrêmiste>
    D'ailleurs, dans un bon design, il n'y a pas de if...
    </mode extrêmiste>

  12. #12
    Membre Expert
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Par défaut
    Effectivement, c'est le pattern Fabrique qu'il faut utiliser. Le code de Davidbrcz est très bien. Je l'ai modifié en enlevant les template (à laisser si tu veux de la généricité) et en introduisant un ptr_map de boost.

    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
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    #include <iostream>
    #include <utility>
    #include <boost/ptr_container/ptr_map.hpp>
     
    struct Message
    {
    	Message() {}
    	virtual ~Message() {}
     
    	virtual Message* Clone() const = 0 ;
    };
     
    struct Message1 : public Message
    {
    	virtual Message* Clone() const { return new Message1; }
    };
     
    struct Message2 : public Message
    {
    	virtual Message* Clone() const { return new Message2; }
    };
     
    class FabriqueMessage
    {
    public:
    	FabriqueMessage() {}
    	virtual ~FabriqueMessage() {}
     
    	virtual Message * creerMessage(int ) const;
    	void Register(int key,Message* obj);
     
    private:
    	boost::ptr_map<int, Message> m_map;
    };
     
    void FabriqueMessage::Register(int key, Message * obj)
    {
    	//si la clé n'est pas déja présente
    	if(m_map.find(key) == m_map.end())
      	{
    		//on ajoute l'objet dans la map
    		m_map.insert(key, obj);
    	}
    //on pourrait détruire obj mais cette tache ne revient pas à la Register
    }
     
    Message* FabriqueMessage::creerMessage(int key) const
    {
    	Message* tmp = 0;
     
    	boost::ptr_map<int, Message>::const_iterator it = m_map.find(key);
     
    	//si l'itérateur ne vaut pas map.end(),cela signifique que la clé à été trouvé     
    	if(it != m_map.end() )
    	{
    		//donc on clone l'objet
          	tmp = (it->second)->Clone();
      	}
    //on pourrai lancer une exeption au besoin
    	return tmp;
    }
     
     
    int main()
    {
    	FabriqueMessage fabrique;
     
    	fabrique.Register(1, new Message1);
    	fabrique.Register(2, new Message2);
     
    	Message * message = fabrique.creerMessage(1);
     
    	delete message;
    	return 0;
    }
    Bonne continuation,

    Poukill

  13. #13
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Par défaut
    Ici l'avantage des templates est de pouvoir créer plusieurs fabrique de chose très différente et de manière transparente
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  14. #14
    Membre Expert
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Par défaut
    Je suis complètement d'accord avec toi, j'ai juste simplifié pour que le collègue comprenne bien!
    Personnellement, je l'utiliserai avec les template, of course !

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

Discussions similaires

  1. Question a propos de LWP::Parallel::UserAgent
    Par shinux2004 dans le forum Modules
    Réponses: 2
    Dernier message: 03/09/2005, 03h01
  2. Question a propos de threads
    Par cryptorchild dans le forum Langage
    Réponses: 1
    Dernier message: 12/07/2005, 11h03
  3. [VBA-E] Question à propos des checkbox
    Par Timfg dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 26/04/2005, 16h09
  4. Question a propos des modulos
    Par barthelv dans le forum Algorithmes et structures de données
    Réponses: 3
    Dernier message: 24/03/2005, 16h56
  5. [debutant] Questions a propos du XML
    Par brune dans le forum XML/XSL et SOAP
    Réponses: 3
    Dernier message: 04/06/2004, 10h39

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