Je suis confronté à un petit problème de syntaxe avec mon code :
template <class T>
class O
{
// ...
};
class A : public O <A::event>
{
public:
class event
{
// ...
};
};
Mais évidemment, le code ne compile pas ("A::event non déclaré"). Et je ne
peux pas utiliser la solution habituelle qui est de déclarer un "class XXX"
avant l'utilisation. Dans mon cas, ça serait :
class A
{
class event;
};
class A : public O <A::event>
{
public:
class event
{
// ...
};
};
qui ne compile bien entendu pas (redéfinition de A). Un "class A::event;" ne
compile évidemment pas non plus...
Quelqu'un a-t-il une idée de comment faire, sachant que je souhaite garder
"event" comme une classe imbriquée dans A (pour des raisons de facilité
d'utilisation et de lisibilité ("event" concerne A)) ?
Merci d'avance pour vos réponses.
Vincent
--
SL> Au fait elle est mieux ma signature maintenant ?
Oui. T'enlève encore les conneries que t'as écrit dedans et c'est bon.
-+- JB in <http://www.le-gnu.net> : Le neuneuttoyage par le vide -+-
| Ce n'est pas forcément ce que tu attends, mais cela t'en rapprochera un | peu. | | class couche | { | class event {...}; | public: | class A : public O<event> {...}; | }; | using couche::A;
| Ce n'est pas forcément ce que tu attends, mais cela t'en rapprochera un
| peu.
|
| class couche
| {
| class event {...};
| public:
| class A : public O<event> {...};
| };
| using couche::A;
| Ce n'est pas forcément ce que tu attends, mais cela t'en rapprochera un | peu. | | class couche | { | class event {...}; | public: | class A : public O<event> {...}; | }; | using couche::A;
Hmm. Je ne comprends pas vraiment ce que tu veux faire avec ça -- mais je suppose que je ne suis pas censé comprendre :-)
Tu veux utiliser un nom avant de l'avoir déclarer. Pour moi, cela indique un problème dans la conception.
Je ne pense pas que le problème vienne d'une erreur de conception. En fait, c'est plutôt une question de style : je tiens à laisser la classe "event" dans A. :-)
Explication complète de mon problème : je dispose d'une classe template "observable" qui est utilisée dans un système de notification :
template <class EVENT_TYPE> class observable { protected:
virtual ~observable() { }
void notify(const EVENT_TYPE& event);
// [...] };
J'ai également plusieurs classes héritant de "observable" qui peuvent émettre chacune leur type d'évènement propre :
class A : public observable <A::event> { public:
class event { /* ... */ } };
class B : public observable <B::event> { public:
class event { /* ... */ } };
// ...etc...
Evidemment le code ci-dessus ne compile pas, et c'est bien là le problème...
D'ailleurs, je ne comprends pas pourquoi C++ n'autorise pas le code montré précédemment : étant donné que la déclaration de la classe n'est pas encore terminée ('};' final), les choses manquantes peuvent encore être déclarées. Dans le cas de l'héritage, je ne pense pas que ça pose un quelconque problème.
Le compilateur pourrait par exemple faire une première "passe" sur le code de déclaration de la classe, puis une deuxième en s'assurant cette fois-ci que tout est bien connu... bon, je suis pas développeur de compilo ! :-)
Vincent
-- SL> Au fait elle est mieux ma signature maintenant ? Oui. T'enlève encore les conneries que t'as écrit dedans et c'est bon. -+- JB in <http://www.le-gnu.net> : Le neuneuttoyage par le vide -+-
Hmm. Je ne comprends pas vraiment ce que tu veux faire avec ça -- mais
je suppose que je ne suis pas censé comprendre :-)
Tu veux utiliser un nom avant de l'avoir déclarer. Pour moi, cela
indique un problème dans la conception.
Je ne pense pas que le problème vienne d'une erreur de conception. En fait,
c'est plutôt une question de style : je tiens à laisser la classe "event"
dans A. :-)
Explication complète de mon problème : je dispose d'une classe template
"observable" qui est utilisée dans un système de notification :
template <class EVENT_TYPE>
class observable
{
protected:
virtual ~observable() { }
void notify(const EVENT_TYPE& event);
// [...]
};
J'ai également plusieurs classes héritant de "observable" qui peuvent
émettre chacune leur type d'évènement propre :
class A : public observable <A::event>
{
public:
class event { /* ... */ }
};
class B : public observable <B::event>
{
public:
class event { /* ... */ }
};
// ...etc...
Evidemment le code ci-dessus ne compile pas, et c'est bien là le problème...
D'ailleurs, je ne comprends pas pourquoi C++ n'autorise pas le code montré
précédemment : étant donné que la déclaration de la classe n'est pas encore
terminée ('};' final), les choses manquantes peuvent encore être déclarées.
Dans le cas de l'héritage, je ne pense pas que ça pose un quelconque
problème.
Le compilateur pourrait par exemple faire une première "passe" sur le code
de déclaration de la classe, puis une deuxième en s'assurant cette fois-ci
que tout est bien connu... bon, je suis pas développeur de compilo ! :-)
Vincent
--
SL> Au fait elle est mieux ma signature maintenant ?
Oui. T'enlève encore les conneries que t'as écrit dedans et c'est bon.
-+- JB in <http://www.le-gnu.net> : Le neuneuttoyage par le vide -+-
Hmm. Je ne comprends pas vraiment ce que tu veux faire avec ça -- mais je suppose que je ne suis pas censé comprendre :-)
Tu veux utiliser un nom avant de l'avoir déclarer. Pour moi, cela indique un problème dans la conception.
Je ne pense pas que le problème vienne d'une erreur de conception. En fait, c'est plutôt une question de style : je tiens à laisser la classe "event" dans A. :-)
Explication complète de mon problème : je dispose d'une classe template "observable" qui est utilisée dans un système de notification :
template <class EVENT_TYPE> class observable { protected:
virtual ~observable() { }
void notify(const EVENT_TYPE& event);
// [...] };
J'ai également plusieurs classes héritant de "observable" qui peuvent émettre chacune leur type d'évènement propre :
class A : public observable <A::event> { public:
class event { /* ... */ } };
class B : public observable <B::event> { public:
class event { /* ... */ } };
// ...etc...
Evidemment le code ci-dessus ne compile pas, et c'est bien là le problème...
D'ailleurs, je ne comprends pas pourquoi C++ n'autorise pas le code montré précédemment : étant donné que la déclaration de la classe n'est pas encore terminée ('};' final), les choses manquantes peuvent encore être déclarées. Dans le cas de l'héritage, je ne pense pas que ça pose un quelconque problème.
Le compilateur pourrait par exemple faire une première "passe" sur le code de déclaration de la classe, puis une deuxième en s'assurant cette fois-ci que tout est bien connu... bon, je suis pas développeur de compilo ! :-)
Vincent
-- SL> Au fait elle est mieux ma signature maintenant ? Oui. T'enlève encore les conneries que t'as écrit dedans et c'est bon. -+- JB in <http://www.le-gnu.net> : Le neuneuttoyage par le vide -+-
d4RK
On 28 Jul 2003, 15:03:37, Luc Hermitte wrote:
Vincent Richard wrote in news:3f25121c$0$1783$:
Je suis confronté à un petit problème de syntaxe avec mon code :
template <class T> class O { // ... };
class A : public O <A::event> { public:
class event { // ... }; };
Mais évidemment, le code ne compile pas ("A::event non déclaré"). Et je ne peux pas utiliser la solution habituelle qui est de déclarer un "class XXX" avant l'utilisation. Dans mon cas, ça serait :
Quelqu'un a-t-il une idée de comment faire, sachant que je souhaite garder "event" comme une classe imbriquée dans A (pour des raisons de facilité d'utilisation et de lisibilité ("event" concerne A)) ?
Ce n'est pas forcément ce que tu attends, mais cela t'en rapprochera un peu.
class couche { class event {...}; public: class A : public O<event> {...}; }; using couche::A;
_____
il est clair qu'il faut laisser la classe 'event' dans la classe A puisqu'elle en est caractéristique, mais on ne peut pas s'en sortir en laissant la classe 'observable' template (impossible à compiler): j'utiliserais plutôt le polymorphisme pour m'en sortir ici, ie: declarer une classe baseEvent de laquelle dériveraient toutes les classes internes 'event' des classes qui en declarent (A pour l'exemple ci-dessus). Observable redevient une classe non-template et 'notify' travaille simplement sur les membres communs des 'event[s]'. Par contre étant donné que je ne vois pas trop ce que fait notify sur son argument, je ne peux pas préciser...
eg: (un truc comme ça :)
class baseEvent{ //membres communs aux events... //des virtuels donc... };
class Observable{ //... void notify(const baseEvent& event); //... };
class A:public observable{ public: class event:public baseEvent{ //... }; //... };
On 28 Jul 2003, 15:03:37, Luc Hermitte wrote:
Vincent Richard <chere-loque.MARRE-DE-LA-PUB@wanadoo.fr.invalid> wrote
in news:3f25121c$0$1783$626a54ce@news.free.fr:
Je suis confronté à un petit problème de syntaxe avec mon code :
template <class T>
class O
{
// ...
};
class A : public O <A::event>
{
public:
class event
{
// ...
};
};
Mais évidemment, le code ne compile pas ("A::event non déclaré"). Et
je ne peux pas utiliser la solution habituelle qui est de déclarer un
"class XXX" avant l'utilisation. Dans mon cas, ça serait :
Quelqu'un a-t-il une idée de comment faire, sachant que je souhaite
garder "event" comme une classe imbriquée dans A (pour des raisons de
facilité d'utilisation et de lisibilité ("event" concerne A)) ?
Ce n'est pas forcément ce que tu attends, mais cela t'en rapprochera un
peu.
class couche
{
class event {...};
public:
class A : public O<event> {...};
};
using couche::A;
_____
il est clair qu'il faut laisser la classe 'event' dans la classe
A puisqu'elle en est caractéristique, mais on ne peut pas s'en
sortir en laissant la classe 'observable' template (impossible
à compiler):
j'utiliserais plutôt le polymorphisme pour m'en sortir ici, ie:
declarer une classe baseEvent de laquelle dériveraient toutes
les classes internes 'event' des classes qui en declarent (A
pour l'exemple ci-dessus). Observable redevient une classe non-template
et 'notify' travaille simplement sur les membres communs des
'event[s]'. Par contre étant donné que je ne vois pas trop ce
que fait notify sur son argument, je ne peux pas préciser...
eg: (un truc comme ça :)
class baseEvent{
//membres communs aux events...
//des virtuels donc...
};
class Observable{
//...
void notify(const baseEvent& event);
//...
};
class A:public observable{
public:
class event:public baseEvent{
//...
};
//...
};
Je suis confronté à un petit problème de syntaxe avec mon code :
template <class T> class O { // ... };
class A : public O <A::event> { public:
class event { // ... }; };
Mais évidemment, le code ne compile pas ("A::event non déclaré"). Et je ne peux pas utiliser la solution habituelle qui est de déclarer un "class XXX" avant l'utilisation. Dans mon cas, ça serait :
Quelqu'un a-t-il une idée de comment faire, sachant que je souhaite garder "event" comme une classe imbriquée dans A (pour des raisons de facilité d'utilisation et de lisibilité ("event" concerne A)) ?
Ce n'est pas forcément ce que tu attends, mais cela t'en rapprochera un peu.
class couche { class event {...}; public: class A : public O<event> {...}; }; using couche::A;
_____
il est clair qu'il faut laisser la classe 'event' dans la classe A puisqu'elle en est caractéristique, mais on ne peut pas s'en sortir en laissant la classe 'observable' template (impossible à compiler): j'utiliserais plutôt le polymorphisme pour m'en sortir ici, ie: declarer une classe baseEvent de laquelle dériveraient toutes les classes internes 'event' des classes qui en declarent (A pour l'exemple ci-dessus). Observable redevient une classe non-template et 'notify' travaille simplement sur les membres communs des 'event[s]'. Par contre étant donné que je ne vois pas trop ce que fait notify sur son argument, je ne peux pas préciser...
eg: (un truc comme ça :)
class baseEvent{ //membres communs aux events... //des virtuels donc... };
class Observable{ //... void notify(const baseEvent& event); //... };
class A:public observable{ public: class event:public baseEvent{ //... }; //... };
Luc Hermitte
Gabriel Dos Reis wrote in news::
| Ce n'est pas forcément ce que tu attends, mais cela t'en rapprochera | un peu. | | class couche { | class event {...}; public: | class A : public O<event> {...}; }; using couche::A;
L'as-tu essayé ?
J'avoue que non.
-- Luc Hermitte <hermitte at free.fr> FAQ de <news:fr.comp.lang.c++> : <http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/> Dejanews : <http://groups.google.com/advanced_group_search>
Gabriel Dos Reis <gdr@integrable-solutions.net> wrote in
news:m3zniy4quk.fsf@uniton.integrable-solutions.net:
| Ce n'est pas forcément ce que tu attends, mais cela t'en rapprochera
| un peu.
|
| class couche {
| class event {...}; public:
| class A : public O<event> {...}; }; using couche::A;
L'as-tu essayé ?
J'avoue que non.
--
Luc Hermitte <hermitte at free.fr>
FAQ de <news:fr.comp.lang.c++> :
<http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/>
Dejanews : <http://groups.google.com/advanced_group_search>
| Ce n'est pas forcément ce que tu attends, mais cela t'en rapprochera | un peu. | | class couche { | class event {...}; public: | class A : public O<event> {...}; }; using couche::A;
L'as-tu essayé ?
J'avoue que non.
-- Luc Hermitte <hermitte at free.fr> FAQ de <news:fr.comp.lang.c++> : <http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/> Dejanews : <http://groups.google.com/advanced_group_search>
Vincent Richard
[PRECISION] L'objet "observable" est censée envoyer des évènements, tandis que l'objet "observer" les reçoit (classique) :
il est clair qu'il faut laisser la classe 'event' dans la classe A puisqu'elle en est caractéristique, mais on ne peut pas s'en sortir en laissant la classe 'observable' template (impossible à compiler): j'utiliserais plutôt le polymorphisme pour m'en sortir ici, ie: declarer une classe baseEvent de laquelle dériveraient toutes les classes internes 'event' des classes qui en declarent (A pour l'exemple ci-dessus). Observable redevient une classe non-template et 'notify' travaille simplement sur les membres communs des 'event[s]'.
Oui, mais cela empêche d'implémenter "observer" pour plusieurs objets différents. Tout du moins, cela nécessite de tout regrouper dans une seule fonction et de tester le type d'évènement (pas très élégant, à mon goût).
Méthode "template" :
class test : public observer <A::event>, public observer <B::event> { void update(const observable <A::event>* o, const A::event& e) { // traitement des évènements de A }
void update(const observable <B::event>* o, const B::event& e) { // traitement des évènements de B } };
Méthode "non-template" :
class test : public observer { // ... void update(const observable* o, const event& e) { if (typeid(e) == typeid(A::event)) { /* traitement A */ } else if (typeid(e) == typeid(B::event)) { /* traitement B */ } } };
Par contre étant donné que je ne vois pas trop ce que fait notify sur son argument, je ne peux pas préciser...
"notify" permet aux classes qui héritent de "observable" d'envoyer un évènement (l'argument) à chacun des observateurs enregistrés auprès de l'observé (classe "observer" et std::vector <observer*> dans l'objet "observable" non présents ici, j'avais simplifié).
Vincent
-- SL> Au fait elle est mieux ma signature maintenant ? Oui. T'enlève encore les conneries que t'as écrit dedans et c'est bon. -+- JB in <http://www.le-gnu.net> : Le neuneuttoyage par le vide -+-
[PRECISION]
L'objet "observable" est censée envoyer des évènements, tandis que
l'objet "observer" les reçoit (classique) :
il est clair qu'il faut laisser la classe 'event' dans la classe
A puisqu'elle en est caractéristique, mais on ne peut pas s'en
sortir en laissant la classe 'observable' template (impossible
à compiler):
j'utiliserais plutôt le polymorphisme pour m'en sortir ici, ie:
declarer une classe baseEvent de laquelle dériveraient toutes
les classes internes 'event' des classes qui en declarent (A
pour l'exemple ci-dessus). Observable redevient une classe non-template
et 'notify' travaille simplement sur les membres communs des
'event[s]'.
Oui, mais cela empêche d'implémenter "observer" pour plusieurs objets
différents. Tout du moins, cela nécessite de tout regrouper dans
une seule fonction et de tester le type d'évènement (pas très élégant,
à mon goût).
Méthode "template" :
class test : public observer <A::event>, public observer <B::event>
{
void update(const observable <A::event>* o, const A::event& e)
{
// traitement des évènements de A
}
void update(const observable <B::event>* o, const B::event& e)
{
// traitement des évènements de B
}
};
Méthode "non-template" :
class test : public observer
{
// ...
void update(const observable* o, const event& e)
{
if (typeid(e) == typeid(A::event))
{ /* traitement A */ }
else if (typeid(e) == typeid(B::event))
{ /* traitement B */ }
}
};
Par contre étant donné que je ne vois pas trop ce
que fait notify sur son argument, je ne peux pas préciser...
"notify" permet aux classes qui héritent de "observable" d'envoyer
un évènement (l'argument) à chacun des observateurs enregistrés auprès
de l'observé (classe "observer" et std::vector <observer*> dans
l'objet "observable" non présents ici, j'avais simplifié).
Vincent
--
SL> Au fait elle est mieux ma signature maintenant ?
Oui. T'enlève encore les conneries que t'as écrit dedans et c'est bon.
-+- JB in <http://www.le-gnu.net> : Le neuneuttoyage par le vide -+-
il est clair qu'il faut laisser la classe 'event' dans la classe A puisqu'elle en est caractéristique, mais on ne peut pas s'en sortir en laissant la classe 'observable' template (impossible à compiler): j'utiliserais plutôt le polymorphisme pour m'en sortir ici, ie: declarer une classe baseEvent de laquelle dériveraient toutes les classes internes 'event' des classes qui en declarent (A pour l'exemple ci-dessus). Observable redevient une classe non-template et 'notify' travaille simplement sur les membres communs des 'event[s]'.
Oui, mais cela empêche d'implémenter "observer" pour plusieurs objets différents. Tout du moins, cela nécessite de tout regrouper dans une seule fonction et de tester le type d'évènement (pas très élégant, à mon goût).
Méthode "template" :
class test : public observer <A::event>, public observer <B::event> { void update(const observable <A::event>* o, const A::event& e) { // traitement des évènements de A }
void update(const observable <B::event>* o, const B::event& e) { // traitement des évènements de B } };
Méthode "non-template" :
class test : public observer { // ... void update(const observable* o, const event& e) { if (typeid(e) == typeid(A::event)) { /* traitement A */ } else if (typeid(e) == typeid(B::event)) { /* traitement B */ } } };
Par contre étant donné que je ne vois pas trop ce que fait notify sur son argument, je ne peux pas préciser...
"notify" permet aux classes qui héritent de "observable" d'envoyer un évènement (l'argument) à chacun des observateurs enregistrés auprès de l'observé (classe "observer" et std::vector <observer*> dans l'objet "observable" non présents ici, j'avais simplifié).
Vincent
-- SL> Au fait elle est mieux ma signature maintenant ? Oui. T'enlève encore les conneries que t'as écrit dedans et c'est bon. -+- JB in <http://www.le-gnu.net> : Le neuneuttoyage par le vide -+-
d4RK
On 28 Jul 2003, 20:17:01, Vincent Richard wrote:
[PRECISION] L'objet "observable" est censée envoyer des évènements, tandis que l'objet "observer" les reçoit (classique) :
il est clair qu'il faut laisser la classe 'event' dans la classe A puisqu'elle en est caractéristique, mais on ne peut pas s'en sortir en laissant la classe 'observable' template (impossible à compiler): j'utiliserais plutôt le polymorphisme pour m'en sortir ici, ie: declarer une classe baseEvent de laquelle dériveraient toutes les classes internes 'event' des classes qui en declarent (A pour l'exemple ci-dessus). Observable redevient une classe non-template et 'notify' travaille simplement sur les membres communs des 'event[s]'.
Oui, mais cela empêche d'implémenter "observer" pour plusieurs objets différents. Tout du moins, cela nécessite de tout regrouper dans une seule fonction et de tester le type d'évènement (pas très élégant, à mon goût).
Méthode "template" :
class test : public observer <A::event>, public observer <B::event> { void update(const observable <A::event>* o, const A::event& e) { // traitement des évènements de A }
void update(const observable <B::event>* o, const B::event& e) { // traitement des évènements de B } };
Méthode "non-template" :
class test : public observer { // ... void update(const observable* o, const event& e) { if (typeid(e) == typeid(A::event)) { /* traitement A */ } else if (typeid(e) == typeid(B::event)) { /* traitement B */ } } };
Par contre étant donné que je ne vois pas trop ce que fait notify sur son argument, je ne peux pas préciser...
"notify" permet aux classes qui héritent de "observable" d'envoyer un évènement (l'argument) à chacun des observateurs enregistrés auprès de l'observé (classe "observer" et std::vector <observer*> dans l'objet "observable" non présents ici, j'avais simplifié).
Vincent
Ok, c'est + clair : J'ai trouvé une solution(?) qui ne t'empêche pas d'avoir un code qui reste 'propre' mais ça rajoute un objet 'bidon' pour chacune de tes classes observables, ie:
au lien de faire:
class A:public Observable<A::Event>{...}
qui reste définitivement incompilable, tu peut faire:
class A{ //la classe A normale... }; class AObservable:public A,public Observable<A::Event>{};
qui rajoute évidemment une classe 'bidon', quoique le tout reste assez cohérent. (on ne peut pas tout avoir!)
En reprenant une synthèse de tes exemples; Voila le code simplifié qui doit faire en gros ce que tu veux (&& qui compile :)
<CODE> #include <iostream> using namespace std;
template<class EVENTTYPE> class Observer;
template<class EVENTTYPE> class Observable{ public: void registerObserver(Observer<EVENTTYPE>* _observer){ myObserver=_observer; } void notify(EVENTTYPE& e){ myObserver->update(*this,e); } private: //normalement un container (vive les listes chainées) //on se contente d'un champ pour le test :) Observer<EVENTTYPE>* myObserver; };
int main(void){ test theObserver; AObservable AO; BObservable BO; AO.registerObserver(&theObserver); BO.registerObserver(&theObserver); AO.notify(AO.ping); return 42; } </CODE>
(comme tu l'as deviné, tu obtiens 'got it! :)' lors de l'exécution) Mais, il est impossible qu'il ait un truc qui m'échappe dans ce que tu veux faire...
On 28 Jul 2003, 20:17:01, Vincent Richard wrote:
[PRECISION]
L'objet "observable" est censée envoyer des évènements, tandis que
l'objet "observer" les reçoit (classique) :
il est clair qu'il faut laisser la classe 'event' dans la classe
A puisqu'elle en est caractéristique, mais on ne peut pas s'en
sortir en laissant la classe 'observable' template (impossible
à compiler):
j'utiliserais plutôt le polymorphisme pour m'en sortir ici, ie:
declarer une classe baseEvent de laquelle dériveraient toutes
les classes internes 'event' des classes qui en declarent (A
pour l'exemple ci-dessus). Observable redevient une classe non-template
et 'notify' travaille simplement sur les membres communs des
'event[s]'.
Oui, mais cela empêche d'implémenter "observer" pour plusieurs objets
différents. Tout du moins, cela nécessite de tout regrouper dans
une seule fonction et de tester le type d'évènement (pas très élégant,
à mon goût).
Méthode "template" :
class test : public observer <A::event>, public observer <B::event>
{
void update(const observable <A::event>* o, const A::event& e)
{
// traitement des évènements de A
}
void update(const observable <B::event>* o, const B::event& e)
{
// traitement des évènements de B
}
};
Méthode "non-template" :
class test : public observer
{
// ...
void update(const observable* o, const event& e)
{
if (typeid(e) == typeid(A::event))
{ /* traitement A */ }
else if (typeid(e) == typeid(B::event))
{ /* traitement B */ }
}
};
Par contre étant donné que je ne vois pas trop ce
que fait notify sur son argument, je ne peux pas préciser...
"notify" permet aux classes qui héritent de "observable" d'envoyer
un évènement (l'argument) à chacun des observateurs enregistrés auprès
de l'observé (classe "observer" et std::vector <observer*> dans
l'objet "observable" non présents ici, j'avais simplifié).
Vincent
Ok, c'est + clair :
J'ai trouvé une solution(?) qui ne t'empêche pas d'avoir un code
qui reste 'propre' mais ça rajoute un objet 'bidon' pour chacune de tes
classes observables, ie:
au lien de faire:
class A:public Observable<A::Event>{...}
qui reste définitivement incompilable, tu peut faire:
class A{
//la classe A normale...
};
class AObservable:public A,public Observable<A::Event>{};
qui rajoute évidemment une classe 'bidon', quoique le tout reste assez
cohérent. (on ne peut pas tout avoir!)
En reprenant une synthèse de tes exemples;
Voila le code simplifié qui doit faire en gros ce que tu veux
(&& qui compile :)
<CODE>
#include <iostream>
using namespace std;
template<class EVENTTYPE> class Observer;
template<class EVENTTYPE>
class Observable{
public:
void registerObserver(Observer<EVENTTYPE>* _observer){
myObserver=_observer;
}
void notify(EVENTTYPE& e){
myObserver->update(*this,e);
}
private:
//normalement un container (vive les listes chainées)
//on se contente d'un champ pour le test :)
Observer<EVENTTYPE>* myObserver;
};
int main(void){
test theObserver;
AObservable AO;
BObservable BO;
AO.registerObserver(&theObserver);
BO.registerObserver(&theObserver);
AO.notify(AO.ping);
return 42;
}
</CODE>
(comme tu l'as deviné, tu obtiens 'got it! :)' lors de l'exécution)
Mais, il est impossible qu'il ait un truc qui m'échappe dans
ce que tu veux faire...
il est clair qu'il faut laisser la classe 'event' dans la classe A puisqu'elle en est caractéristique, mais on ne peut pas s'en sortir en laissant la classe 'observable' template (impossible à compiler): j'utiliserais plutôt le polymorphisme pour m'en sortir ici, ie: declarer une classe baseEvent de laquelle dériveraient toutes les classes internes 'event' des classes qui en declarent (A pour l'exemple ci-dessus). Observable redevient une classe non-template et 'notify' travaille simplement sur les membres communs des 'event[s]'.
Oui, mais cela empêche d'implémenter "observer" pour plusieurs objets différents. Tout du moins, cela nécessite de tout regrouper dans une seule fonction et de tester le type d'évènement (pas très élégant, à mon goût).
Méthode "template" :
class test : public observer <A::event>, public observer <B::event> { void update(const observable <A::event>* o, const A::event& e) { // traitement des évènements de A }
void update(const observable <B::event>* o, const B::event& e) { // traitement des évènements de B } };
Méthode "non-template" :
class test : public observer { // ... void update(const observable* o, const event& e) { if (typeid(e) == typeid(A::event)) { /* traitement A */ } else if (typeid(e) == typeid(B::event)) { /* traitement B */ } } };
Par contre étant donné que je ne vois pas trop ce que fait notify sur son argument, je ne peux pas préciser...
"notify" permet aux classes qui héritent de "observable" d'envoyer un évènement (l'argument) à chacun des observateurs enregistrés auprès de l'observé (classe "observer" et std::vector <observer*> dans l'objet "observable" non présents ici, j'avais simplifié).
Vincent
Ok, c'est + clair : J'ai trouvé une solution(?) qui ne t'empêche pas d'avoir un code qui reste 'propre' mais ça rajoute un objet 'bidon' pour chacune de tes classes observables, ie:
au lien de faire:
class A:public Observable<A::Event>{...}
qui reste définitivement incompilable, tu peut faire:
class A{ //la classe A normale... }; class AObservable:public A,public Observable<A::Event>{};
qui rajoute évidemment une classe 'bidon', quoique le tout reste assez cohérent. (on ne peut pas tout avoir!)
En reprenant une synthèse de tes exemples; Voila le code simplifié qui doit faire en gros ce que tu veux (&& qui compile :)
<CODE> #include <iostream> using namespace std;
template<class EVENTTYPE> class Observer;
template<class EVENTTYPE> class Observable{ public: void registerObserver(Observer<EVENTTYPE>* _observer){ myObserver=_observer; } void notify(EVENTTYPE& e){ myObserver->update(*this,e); } private: //normalement un container (vive les listes chainées) //on se contente d'un champ pour le test :) Observer<EVENTTYPE>* myObserver; };
int main(void){ test theObserver; AObservable AO; BObservable BO; AO.registerObserver(&theObserver); BO.registerObserver(&theObserver); AO.notify(AO.ping); return 42; } </CODE>
(comme tu l'as deviné, tu obtiens 'got it! :)' lors de l'exécution) Mais, il est impossible qu'il ait un truc qui m'échappe dans ce que tu veux faire...
d4RK
On 28 Jul 2003, 19:51:42, d4RK wrote:
[...] } </CODE>
(comme tu l'as deviné, tu obtiens 'got it! :)' lors de l'exécution) Mais, il est impossible qu'il ait un truc qui m'échappe dans ce que tu veux faire...
je voulais évidemment dire "il est **possible** qu'il ait qq chose qui m'échappe " ;)
On 28 Jul 2003, 19:51:42, d4RK wrote:
[...]
}
</CODE>
(comme tu l'as deviné, tu obtiens 'got it! :)' lors de l'exécution)
Mais, il est impossible qu'il ait un truc qui m'échappe dans
ce que tu veux faire...
je voulais évidemment dire "il est **possible** qu'il ait qq
chose qui m'échappe " ;)
(comme tu l'as deviné, tu obtiens 'got it! :)' lors de l'exécution) Mais, il est impossible qu'il ait un truc qui m'échappe dans ce que tu veux faire...
je voulais évidemment dire "il est **possible** qu'il ait qq chose qui m'échappe " ;)
Vincent Richard
J'ai trouvé une solution(?) qui ne t'empêche pas d'avoir un code qui reste 'propre' mais ça rajoute un objet 'bidon' pour chacune de tes classes observables, ie:
au lien de faire:
class A:public Observable<A::Event>{...}
qui reste définitivement incompilable, tu peut faire:
class A{ //la classe A normale... }; class AObservable:public A,public Observable<A::Event>{};
qui rajoute évidemment une classe 'bidon', quoique le tout reste assez cohérent. (on ne peut pas tout avoir!)
Merci, cette solution me convient. Du point de vue intérieur (code), ce n'est pas très "élégant", mais ce qui compte, c'est au niveau de l'utilisateur, et là les exigences sont respectées (modulo le fait que la classe "bidon" pollue l'espace de noms, mais on ne peut pas tout avoir...).
Bon, n'empêche que ça serait pas mal que les compilateurs acceptent cette foutue syntaxe ! ;-)
Vincent
-- SL> Au fait elle est mieux ma signature maintenant ? Oui. T'enlève encore les conneries que t'as écrit dedans et c'est bon. -+- JB in <http://www.le-gnu.net> : Le neuneuttoyage par le vide -+-
J'ai trouvé une solution(?) qui ne t'empêche pas d'avoir un code
qui reste 'propre' mais ça rajoute un objet 'bidon' pour chacune de tes
classes observables, ie:
au lien de faire:
class A:public Observable<A::Event>{...}
qui reste définitivement incompilable, tu peut faire:
class A{
//la classe A normale...
};
class AObservable:public A,public Observable<A::Event>{};
qui rajoute évidemment une classe 'bidon', quoique le tout reste assez
cohérent. (on ne peut pas tout avoir!)
Merci, cette solution me convient. Du point de vue intérieur (code), ce
n'est pas très "élégant", mais ce qui compte, c'est au niveau de
l'utilisateur, et là les exigences sont respectées (modulo le fait
que la classe "bidon" pollue l'espace de noms, mais on ne peut pas
tout avoir...).
Bon, n'empêche que ça serait pas mal que les compilateurs acceptent
cette foutue syntaxe ! ;-)
Vincent
--
SL> Au fait elle est mieux ma signature maintenant ?
Oui. T'enlève encore les conneries que t'as écrit dedans et c'est bon.
-+- JB in <http://www.le-gnu.net> : Le neuneuttoyage par le vide -+-
J'ai trouvé une solution(?) qui ne t'empêche pas d'avoir un code qui reste 'propre' mais ça rajoute un objet 'bidon' pour chacune de tes classes observables, ie:
au lien de faire:
class A:public Observable<A::Event>{...}
qui reste définitivement incompilable, tu peut faire:
class A{ //la classe A normale... }; class AObservable:public A,public Observable<A::Event>{};
qui rajoute évidemment une classe 'bidon', quoique le tout reste assez cohérent. (on ne peut pas tout avoir!)
Merci, cette solution me convient. Du point de vue intérieur (code), ce n'est pas très "élégant", mais ce qui compte, c'est au niveau de l'utilisateur, et là les exigences sont respectées (modulo le fait que la classe "bidon" pollue l'espace de noms, mais on ne peut pas tout avoir...).
Bon, n'empêche que ça serait pas mal que les compilateurs acceptent cette foutue syntaxe ! ;-)
Vincent
-- SL> Au fait elle est mieux ma signature maintenant ? Oui. T'enlève encore les conneries que t'as écrit dedans et c'est bon. -+- JB in <http://www.le-gnu.net> : Le neuneuttoyage par le vide -+-
Gabriel Dos Reis
Vincent Richard writes:
| Bon, n'empêche que ça serait pas mal que les compilateurs acceptent | cette foutue syntaxe ! ;-)
c'est pas demain la veille ;-)
-- Gaby
Vincent Richard <chere-loque.MARRE-DE-LA-PUB@wanadoo.fr.invalid> writes:
| Bon, n'empêche que ça serait pas mal que les compilateurs acceptent
| cette foutue syntaxe ! ;-)