 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Christophe Lephay Guest
|
Posted: Thu Jul 17, 2003 7:12 pm Post subject: Re: Question de design |
|
|
"amerio" <amerio (AT) hotmail (DOT) com> a écrit dans le message de
news:XFBRa.212212$1F6.2229356 (AT) news (DOT) chello.at...
| Quote: | Bonjour,
Supposons que j'ai une classe Objet et deux sous classes ObjetA et ObjetB,
*déjà existants* (je ne peux pas les modifier).
Je dois "rajouter" des membres/méthodes à Objet, et par extension à tous
ces
dérivés.
Ce que je fais actuellement, c'est écrire une classe Super avec toutes les
fonctionnalités que je voudrais rajouter, puis je fais de l'héritahe
multiple :
class SuperA : public ObjetA, public Super
class SuperB : public ObjetB, public Super
SuperA et B sont donc des 'Objet', et ont les fonctionnalités de Super.
Là ou il y a un pb, c'est que Super doit pouvoir utiliser les méthodes
publiques d'un Objet.
Donc pour l'instant, le constructeur de Super prend un pointeur sur un
Objet
associé.
Super::Super(Objet* pObjet):m_pObjet(pObjet){}
Et je construits un SuperA ainsi :
SuperA::SuperA():Super(this){}
Cette construction marche, mais je me demande s'il n'y pas pas moyen de
faire mieux...
C'est peut-etre une pattern que je n'aurais pas reconnue ?
|
tout dépend de tes contraintes. Selon le cas, tu peux aussi utiliser la
composition au lieu de faire hériter tes classes SuperX, et de redéfinir
complètement l'interface (en gardant les mêmes signatures pour les méthodes
de ObjetX si nécessaire). De cette manière, tu évites l'héritage multiple,
ce qui peut ne pas être dénué d'intéret. En C++, tu peux également gagner en
automatisation en faisant de tes ObjetX un type fourni en paramètre pour tes
classes SuperX. Il y a en fait pas mal de solutions, mais sans connaitre
plus de détail, je ne crois pas qu'on puisse dire quelle est la meilleure
méthode.
Chris
|
|
| Back to top |
|
 |
amerio Guest
|
Posted: Thu Jul 17, 2003 7:30 pm Post subject: Re: Question de design |
|
|
| Quote: | Supposons que j'ai une classe Objet et deux sous classes ObjetA et
ObjetB,
*déjà existants* (je ne peux pas les modifier).
Je dois "rajouter" des membres/méthodes à Objet, et par extension à tous
ces
dérivés.
Ce que je fais actuellement, c'est écrire une classe Super avec toutes
les
fonctionnalités que je voudrais rajouter, puis je fais de l'héritahe
multiple :
class SuperA : public ObjetA, public Super
class SuperB : public ObjetB, public Super
SuperA et B sont donc des 'Objet', et ont les fonctionnalités de Super.
Là ou il y a un pb, c'est que Super doit pouvoir utiliser les méthodes
publiques d'un Objet.
Donc pour l'instant, le constructeur de Super prend un pointeur sur un
Objet
associé.
Super::Super(Objet* pObjet):m_pObjet(pObjet){}
Et je construits un SuperA ainsi :
SuperA::SuperA():Super(this){}
Cette construction marche, mais je me demande s'il n'y pas pas moyen de
faire mieux...
C'est peut-etre une pattern que je n'aurais pas reconnue ?
tout dépend de tes contraintes. Selon le cas, tu peux aussi utiliser la
composition au lieu de faire hériter tes classes SuperX, et de redéfinir
complètement l'interface (en gardant les mêmes signatures pour les
méthodes
de ObjetX si nécessaire). De cette manière, tu évites l'héritage multiple,
ce qui peut ne pas être dénué d'intéret. En C++, tu peux également gagner
en
automatisation en faisant de tes ObjetX un type fourni en paramètre pour
tes
classes SuperX. Il y a en fait pas mal de solutions, mais sans connaitre
plus de détail, je ne crois pas qu'on puisse dire quelle est la meilleure
méthode.
|
J'avais écarté la composition car trop lourde dans mon cas (Objet est assez
fourni...)
De plus, tous mes Objet sont gérés par un conteneur spécialisé (Manager),
qui stocke uniquement des pointeurs sur Objet, donc la composition n'aurait
pas marché.
Manager::Add(Objet*), et bien sûr je ne peux pas modifier le Manager, ni les
classes Objet.
Toutes les methodes qu'apporte Super sont à usage interne uniquement (cad
que seul Super les utilisent, voire les méthodes surchargées de Objet par
SuperX)
class Objet{virtual void Manage() = 0;}
class ObjetA{virtual void Manage();}
class Super{virtual void Work();}
class SuperA: public ObjetA, public Super
{
virtual void Manage() { ObjetA::Manage(); Work(); }
}
void Manager::Manage() { ... pObject->Manage(); ... }
|
|
| Back to top |
|
 |
geranium Guest
|
Posted: Thu Jul 17, 2003 8:09 pm Post subject: Re: Question de design |
|
|
bonjour
ah, réduire le couplage, réduire le couplage... là c'est un plat de
spagguetti )
moi je ferais :
Super implemente les nouvelles fonctionnalites et a une reference sur Objet
:
Super::Super(Objet* pObjet):m_pObjet(pObjet){}
Super::NouvelleFunc1
Super::FuncObj(){pObjet->Func()} // delegation de methodes sur Objet
SuperA et SuperB sont sous classes de super (et c'est tout !)
ou bien ?
"amerio" <amerio (AT) hotmail (DOT) com> a écrit dans le message de
news:XFBRa.212212$1F6.2229356 (AT) news (DOT) chello.at...
| Quote: | Bonjour,
Supposons que j'ai une classe Objet et deux sous classes ObjetA et ObjetB,
*déjà existants* (je ne peux pas les modifier).
Je dois "rajouter" des membres/méthodes à Objet, et par extension à tous
ces
dérivés.
Ce que je fais actuellement, c'est écrire une classe Super avec toutes les
fonctionnalités que je voudrais rajouter, puis je fais de l'héritahe
multiple :
class SuperA : public ObjetA, public Super
class SuperB : public ObjetB, public Super
SuperA et B sont donc des 'Objet', et ont les fonctionnalités de Super.
Là ou il y a un pb, c'est que Super doit pouvoir utiliser les méthodes
publiques d'un Objet.
Donc pour l'instant, le constructeur de Super prend un pointeur sur un
Objet
associé.
Super::Super(Objet* pObjet):m_pObjet(pObjet){}
Et je construits un SuperA ainsi :
SuperA::SuperA():Super(this){}
Cette construction marche, mais je me demande s'il n'y pas pas moyen de
faire mieux...
C'est peut-etre une pattern que je n'aurais pas reconnue ?
|
|
|
| Back to top |
|
 |
amerio Guest
|
Posted: Thu Jul 17, 2003 8:23 pm Post subject: Re: Question de design |
|
|
[reponse en bas]
| Quote: |
"amerio" <amerio (AT) hotmail (DOT) com> a écrit dans le message de
news:XFBRa.212212$1F6.2229356 (AT) news (DOT) chello.at...
Bonjour,
Supposons que j'ai une classe Objet et deux sous classes ObjetA et
ObjetB,
*déjà existants* (je ne peux pas les modifier).
Je dois "rajouter" des membres/méthodes à Objet, et par extension à tous
ces
dérivés.
Ce que je fais actuellement, c'est écrire une classe Super avec toutes
les
fonctionnalités que je voudrais rajouter, puis je fais de l'héritahe
multiple :
class SuperA : public ObjetA, public Super
class SuperB : public ObjetB, public Super
SuperA et B sont donc des 'Objet', et ont les fonctionnalités de Super.
Là ou il y a un pb, c'est que Super doit pouvoir utiliser les méthodes
publiques d'un Objet.
Donc pour l'instant, le constructeur de Super prend un pointeur sur un
Objet
associé.
Super::Super(Objet* pObjet):m_pObjet(pObjet){}
Et je construits un SuperA ainsi :
SuperA::SuperA():Super(this){}
Cette construction marche, mais je me demande s'il n'y pas pas moyen de
faire mieux...
C'est peut-etre une pattern que je n'aurais pas reconnue ?
ah, réduire le couplage, réduire le couplage... là c'est un plat de
spagguetti )
|
hehe, c'est pas si simple, hélas...
| Quote: | moi je ferais :
Super implemente les nouvelles fonctionnalites et a une reference sur
Objet
:
Super::Super(Objet* pObjet):m_pObjet(pObjet){}
Super::NouvelleFunc1
Super::FuncObj(){pObjet->Func()} // delegation de methodes sur Objet
SuperA et SuperB sont sous classes de super (et c'est tout !)
ou bien ?
|
Et bien cela je ne peux pas. J'avais certes oublié de dire que tous ces
Objets sont gérés par un Manager (qui ne prend que des Objet*). Des Super ne
dérivant pas de Objet ne conviennent donc pas
(voir mon autre post)
En fait, pour le monde extérieur, je ne rajoute _rien_ à Objet (je ne change
pas l'interface pour Manager, qui ne connait en fait "que"
Objet::Manage()..., et ignore Super). Par contre, SuperX modifie Manage, en
appelant des méthodes de Super...
Je ne sais pas si une autre solution existe, mais il y a tant de choses à
apprendre :-)
|
|
| Back to top |
|
 |
Christophe Lephay Guest
|
Posted: Thu Jul 17, 2003 10:41 pm Post subject: Re: Question de design |
|
|
"amerio" <amerio (AT) hotmail (DOT) com> a écrit dans le message de
news:4PCRa.213445$1F6.2239234 (AT) news (DOT) chello.at...
| Quote: | J'avais écarté la composition car trop lourde dans mon cas (Objet est
assez
fourni...)
|
Ce n'est pas un argument pertinent, car même si ça peut sembler lourd à
écrire, tu ne l'écris qu'une seule fois (comparé aux n utilisations, c'est
traditionnellement largement amortit)...
| Quote: | De plus, tous mes Objet sont gérés par un conteneur spécialisé (Manager),
qui stocke uniquement des pointeurs sur Objet, donc la composition
n'aurait
pas marché.
Manager::Add(Objet*), et bien sûr je ne peux pas modifier le Manager, ni
les
classes Objet.
|
Si tu utilises l'héritage multiple, pense à faire un héritage virtuel si tu
veux conserver le polymorphisme...
| Quote: | Toutes les methodes qu'apporte Super sont à usage interne uniquement (cad
que seul Super les utilisent, voire les méthodes surchargées de Objet par
SuperX)
class Objet{virtual void Manage() = 0;}
class ObjetA{virtual void Manage();}
class Super{virtual void Work();}
class SuperA: public ObjetA, public Super
{
virtual void Manage() { ObjetA::Manage(); Work(); }
}
void Manager::Manage() { ... pObject->Manage(); ... }
|
La composition reste néanmoins possible :
class SuperObjetA : public ObjetA
{
Super * pSuper;
....
void Manage() { ObjetA::Manage(); pSuper->Work(); }
};
Chris
|
|
| Back to top |
|
 |
amerio Guest
|
Posted: Fri Jul 18, 2003 7:02 am Post subject: Re: Question de design |
|
|
| Quote: | Ce n'est pas un argument pertinent, car même si ça peut sembler lourd à
écrire, tu ne l'écris qu'une seule fois (comparé aux n utilisations, c'est
traditionnellement largement amortit)...
|
C'est vrai .... sauf que dans mon cas, Objet - bien que je ne puisse pas le
changer *moi* - peut évoluer (autre équipe). Dans ce cas, reporter les
modifs sur Objet devient lourd.
Sinon, je suis d'accord avec toi, le coup serait amorti.
| Quote: | De plus, tous mes Objet sont gérés par un conteneur spécialisé
(Manager),
qui stocke uniquement des pointeurs sur Objet, donc la composition
n'aurait
pas marché.
Manager::Add(Objet*), et bien sûr je ne peux pas modifier le Manager, ni
les
classes Objet.
Si tu utilises l'héritage multiple, pense à faire un héritage virtuel si
tu
veux conserver le polymorphisme...
L'héritage virtuel ne sert que si la classe de base est plus d'une fois dans |
la hiérarchie, non ?
Et ce n'est pas le cas, ici ! Ou me-trompe-je ?
| Quote: |
Toutes les methodes qu'apporte Super sont à usage interne uniquement
(cad
que seul Super les utilisent, voire les méthodes surchargées de Objet
par
SuperX)
class Objet{virtual void Manage() = 0;}
class ObjetA{virtual void Manage();}
class Super{virtual void Work();}
class SuperA: public ObjetA, public Super
{
virtual void Manage() { ObjetA::Manage(); Work(); }
}
void Manager::Manage() { ... pObject->Manage(); ... }
La composition reste néanmoins possible :
class SuperObjetA : public ObjetA
{
Super * pSuper;
...
void Manage() { ObjetA::Manage(); pSuper->Work(); }
};
|
Oui, effectivemnt, ca marche aussi comme ca !
Je vais y réfléchir... merci !
|
|
| Back to top |
|
 |
Arnaud Debaene Guest
|
Posted: Fri Jul 18, 2003 11:25 am Post subject: Re: Question de design |
|
|
"amerio" <amerio (AT) hotmail (DOT) com> wrote
| Quote: | Bonjour,
Supposons que j'ai une classe Objet et deux sous classes ObjetA et ObjetB,
*déjà existants* (je ne peux pas les modifier).
Je dois "rajouter" des membres/méthodes à Objet, et par extension à tous ces
dérivés.
Ce que je fais actuellement, c'est écrire une classe Super avec toutes les
fonctionnalités que je voudrais rajouter, puis je fais de l'héritahe
multiple :
class SuperA : public ObjetA, public Super
class SuperB : public ObjetB, public Super
SuperA et B sont donc des 'Objet', et ont les fonctionnalités de Super.
Là ou il y a un pb, c'est que Super doit pouvoir utiliser les méthodes
publiques d'un Objet.
Donc pour l'instant, le constructeur de Super prend un pointeur sur un Objet
associé.
Super::Super(Objet* pObjet):m_pObjet(pObjet){}
Et je construits un SuperA ainsi :
SuperA::SuperA():Super(this){}
Cette construction marche, mais je me demande s'il n'y pas pas moyen de
faire mieux...
C'est peut-etre une pattern que je n'aurais pas reconnue ?
|
Est-ce quelque chose comme ceci ferait l'affaire? :
template <class T> class Super : public T
{
//blabla
};
typedef Super<ObjetA> SuperA;
typedef Super<ObjetB> SuperB;
Tu évites l'héritage multiple, tes objets sont toujours des Objet et
donc manipulables par ton Manager.
Arnaud
|
|
| Back to top |
|
 |
amerio Guest
|
Posted: Fri Jul 18, 2003 4:23 pm Post subject: Re: Question de design |
|
|
| Quote: | Supposons que j'ai une classe Objet et deux sous classes ObjetA et
ObjetB,
*déjà existants* (je ne peux pas les modifier).
Je dois "rajouter" des membres/méthodes à Objet, et par extension à tous
ces
dérivés.
Ce que je fais actuellement, c'est écrire une classe Super avec toutes
les
fonctionnalités que je voudrais rajouter, puis je fais de l'héritahe
multiple :
class SuperA : public ObjetA, public Super
class SuperB : public ObjetB, public Super
SuperA et B sont donc des 'Objet', et ont les fonctionnalités de Super.
Là ou il y a un pb, c'est que Super doit pouvoir utiliser les méthodes
publiques d'un Objet.
Donc pour l'instant, le constructeur de Super prend un pointeur sur un
Objet
associé.
Super::Super(Objet* pObjet):m_pObjet(pObjet){}
Et je construits un SuperA ainsi :
SuperA::SuperA():Super(this){}
Cette construction marche, mais je me demande s'il n'y pas pas moyen de
faire mieux...
C'est peut-etre une pattern que je n'aurais pas reconnue ?
Est-ce quelque chose comme ceci ferait l'affaire? :
template <class T> class Super : public T
{
//blabla
};
typedef Super<ObjetA> SuperA;
typedef Super<ObjetB> SuperB;
Tu évites l'héritage multiple, tes objets sont toujours des Objet et
donc manipulables par ton Manager.
|
Oui, cela peut resoudre mon problème, mais je regrette que le template
m'oblige à tout mettre dans le .h
Bien sur, je pourrais faire un '.inl' plutot qu'un cpp (ou inclure et ne pas
compiler le .cpp)
L'autre avantage est que je pourrais utiliser directement les méthodes de
Objet, sans passer par un pointeur (si je ne me trompe pas).
Par contre pour le typedef, je ne comprend pas. SuperA n'est pas juste un
mix de Super et ObjetA, mais doit pouvoir les étendre (héritage).
Peut-etre que cela convient :
class SuperA : public Super<ObjetA>
{
....
}
Par contre, encore une question :
Si je construits ainsi SuperA et SuperB, puis-je faire un static_cast vers
l'un ou l'autre à partir d'un Super* ? (et d'abord, comment le construire si
c'est un template ??)
|
|
| Back to top |
|
 |
Arnaud Debaene Guest
|
Posted: Fri Jul 18, 2003 6:30 pm Post subject: Re: Question de design |
|
|
amerio wrote:
| Quote: | Est-ce quelque chose comme ceci ferait l'affaire? :
template <class T> class Super : public T
{
//blabla
};
typedef Super<ObjetA> SuperA;
typedef Super<ObjetB> SuperB;
Tu évites l'héritage multiple, tes objets sont toujours des Objet et
donc manipulables par ton Manager.
Oui, cela peut resoudre mon problème, mais je regrette que le template
m'oblige à tout mettre dans le .h
Eternel problèmes des templates, jusqu'à ce que export sot disponible sur |
ton compilateur préféré.
| Quote: | L'autre avantage est que je pourrais utiliser directement les
méthodes de Objet, sans passer par un pointeur (si je ne me trompe
pas).
Dans quel contexte? Effectivement, SuperA et SuperB héritent publiquement de |
Objet, donc ses méthodes sont disponibles dans leur implémentation.
| Quote: | Par contre pour le typedef, je ne comprend pas. SuperA n'est pas
juste un mix de Super et ObjetA, mais doit pouvoir les étendre
(héritage).
Peut-etre que cela convient :
class SuperA : public Super
{
...
}
Ah, ok, j'avais pas compris que SuperA et SuperB définissaient un niveau de |
spécialisation supplémentaire.
| Quote: | Par contre, encore une question :
Si je construits ainsi SuperA et SuperB, puis-je faire un static_cast
vers l'un ou l'autre à partir d'un Super* ? (et d'abord, comment le
construire si c'est un template ??)
|
Super n'est pas un type en tant que tel. Tu ne peux pas définir de Super*,
tu ne peux instancier que des spécialisations complètes. Je ne vois pas trop
où tu veux en venir là....
Arnaud
|
|
| Back to top |
|
 |
amerio Guest
|
Posted: Fri Jul 18, 2003 7:52 pm Post subject: Re: Question de design |
|
|
| Quote: | Si je construits ainsi SuperA et SuperB, puis-je faire un static_cast
vers l'un ou l'autre à partir d'un Super* ? (et d'abord, comment le
construire si c'est un template ??)
Super n'est pas un type en tant que tel. Tu ne peux pas définir de Super*,
tu ne peux instancier que des spécialisations complètes. Je ne vois pas
trop
où tu veux en venir là....
|
Il est bien sur évident que Super* n'est pas définissable.
En fait, ma question venait du fait que j'utilise actuellement un tableau de
Super* pour contenir ceux de mes Objet qui dérivent par héritage multiple de
Super et Objet.
Donc j'ai un tableau de Super*... Que je ne peux plus écrire si je fais un
template.
Au passage, supposons que j'ai un pointeur sur un Objet, dont je sois *sur*
qu'il est aussi un Super<Objet>.
J'ai donc :
Objet* pObjet ; // pObjet = new SuperA; ou SuperB; c'est sur
Comment accéder au méthode de Super via pObjet ? (communes à SuperA et
SuperB, mais par contre je ne sais pas si c'est un SuperA ou B, juste un
Super...)
|
|
| Back to top |
|
 |
Christophe Lephay Guest
|
Posted: Fri Jul 18, 2003 11:00 pm Post subject: Re: Question de design |
|
|
"amerio" <amerio (AT) hotmail (DOT) com> a écrit dans le message de
news:PdYRa.233259$1F6.2436072 (AT) news (DOT) chello.at...
| Quote: | Si je construits ainsi SuperA et SuperB, puis-je faire un static_cast
vers l'un ou l'autre à partir d'un Super* ? (et d'abord, comment le
construire si c'est un template ??)
Super n'est pas un type en tant que tel. Tu ne peux pas définir de
Super*,
tu ne peux instancier que des spécialisations complètes. Je ne vois pas
trop
où tu veux en venir là....
Il est bien sur évident que Super* n'est pas définissable.
En fait, ma question venait du fait que j'utilise actuellement un tableau
de
Super* pour contenir ceux de mes Objet qui dérivent par héritage multiple
de
Super et Objet.
Donc j'ai un tableau de Super*... Que je ne peux plus écrire si je fais un
template.
|
Tu peux très bien regler ce problème à peu de frais :
class Super
{
....
virtual void work() = 0;
....
};
template< class T >
SuperObjet : virtual public Objet, virtual public Super
{
void work();
void methode() { T::methode(); work(); }
};
| Quote: | Au passage, supposons que j'ai un pointeur sur un Objet, dont je sois
*sur*
qu'il est aussi un Super<Objet>.
J'ai donc :
Objet* pObjet ; // pObjet = new SuperA; ou SuperB; c'est sur
Comment accéder au méthode de Super via pObjet ? (communes à SuperA et
SuperB, mais par contre je ne sais pas si c'est un SuperA ou B, juste un
Super...)
|
Un dynamic_cast< Super * > ne fait pas l'affaire ?
Chris
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|