j'ai la classe suivante, qui me sert à étaler dans le temps une
succession de requêtes à une base de données. (Tant qu'il y a des
requêtes dans liste_attente, le Timer tourne, sinon tout se met en pause)
Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
Jean-Marc Bourguet
Michael writes:
Comment je peux rendre cette classe plus générique, donc Comment je peux faire pour appeller n'importe quelle fonction dans Attente::Add()???
Regarde les signaux. Il y en a chez boost, il y a aussi libsig++ (utilisé par gtk--/gtkmm). Sinon avec google tu devrais pouvoir retrouver des messages où c'est expliqué comment faire; il me semble qu'il y en a un de moi.
A+
-- Jean-Marc FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html Site de usenet-fr: http://www.usenet-fr.news.eu.org
Michael <michael_delva.enlever@hotmail.com> writes:
Comment je peux rendre cette classe plus générique, donc
Comment je peux faire pour appeller n'importe quelle fonction dans
Attente::Add()???
Regarde les signaux. Il y en a chez boost, il y a aussi
libsig++ (utilisé par gtk--/gtkmm). Sinon avec google tu
devrais pouvoir retrouver des messages où c'est expliqué
comment faire; il me semble qu'il y en a un de moi.
A+
--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Comment je peux rendre cette classe plus générique, donc Comment je peux faire pour appeller n'importe quelle fonction dans Attente::Add()???
Regarde les signaux. Il y en a chez boost, il y a aussi libsig++ (utilisé par gtk--/gtkmm). Sinon avec google tu devrais pouvoir retrouver des messages où c'est expliqué comment faire; il me semble qu'il y en a un de moi.
A+
-- Jean-Marc FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html Site de usenet-fr: http://www.usenet-fr.news.eu.org
Ahmed MOHAMED ALI
Bonjour,
Attente->Add(BDD->Execute_Query(.....));
Mais je pourrais aussi faire:
Attente->Add(toto->OnSenFout(...));
A moins que je n'ai pas compris ta problématique,tu n'as pas besoin de pointeur de fonction là. N'importe quel fonction (globale ou membre de classe) convient si elle renvoie un AnsiString .
Ahmed MOHAMED ALI
"Michael" wrote in message news:
Bonjour à tous,
j'ai la classe suivante, qui me sert à étaler dans le temps une succession de requêtes à une base de données. (Tant qu'il y a des requêtes dans liste_attente, le Timer tourne, sinon tout se met en pause)
Donc là c'est une utilisation très spécialisée, puisque je passe la requête à Add, qui s'occupe du reste...
Comment je peux rendre cette classe plus générique, donc Comment je peux faire pour appeller n'importe quelle fonction dans Attente::Add()???
Par exemple dans le code j'aurais:
Attente->Add(BDD->Execute_Query(.....));
Mais je pourrais aussi faire:
Attente->Add(toto->OnSenFout(...));
J'espère avoir été clair!
Merci d'avance...
Bonjour,
Attente->Add(BDD->Execute_Query(.....));
Mais je pourrais aussi faire:
Attente->Add(toto->OnSenFout(...));
A moins que je n'ai pas compris ta problématique,tu n'as pas besoin de
pointeur de fonction là.
N'importe quel fonction (globale ou membre de classe) convient si elle
renvoie un AnsiString .
Ahmed MOHAMED ALI
"Michael" <michael_delva.enlever@hotmail.com> wrote in message
news:Xns9630CC9EFEE0Fmichaeldelvaenleverh@212.27.42.67...
Bonjour à tous,
j'ai la classe suivante, qui me sert à étaler dans le temps une
succession de requêtes à une base de données. (Tant qu'il y a des
requêtes dans liste_attente, le Timer tourne, sinon tout se met en pause)
A moins que je n'ai pas compris ta problématique,tu n'as pas besoin de pointeur de fonction là. N'importe quel fonction (globale ou membre de classe) convient si elle renvoie un AnsiString .
Ahmed MOHAMED ALI
"Michael" wrote in message news:
Bonjour à tous,
j'ai la classe suivante, qui me sert à étaler dans le temps une succession de requêtes à une base de données. (Tant qu'il y a des requêtes dans liste_attente, le Timer tourne, sinon tout se met en pause)
Donc là c'est une utilisation très spécialisée, puisque je passe la requête à Add, qui s'occupe du reste...
Comment je peux rendre cette classe plus générique, donc Comment je peux faire pour appeller n'importe quelle fonction dans Attente::Add()???
Par exemple dans le code j'aurais:
Attente->Add(BDD->Execute_Query(.....));
Mais je pourrais aussi faire:
Attente->Add(toto->OnSenFout(...));
J'espère avoir été clair!
Merci d'avance...
Michael
"Ahmed MOHAMED ALI" wrote in news:42543177$0$11698$:
Bonjour,
Attente->Add(BDD->Execute_Query(.....));
Mais je pourrais aussi faire:
Attente->Add(toto->OnSenFout(...));
A moins que je n'ai pas compris ta problématique,tu n'as pas besoin de pointeur de fonction là. N'importe quel fonction (globale ou membre de classe) convient si elle renvoie un AnsiString .
là, Add(const AnsiString & query), c'est pour l'exemple...
je voudrais que Add(...) puisse pointer vers une fonction, peut-importe laquelle, et que cette fonction soit exécutée quand le Timer le décide...
"Ahmed MOHAMED ALI" <NOSPAMahmedmoali@wanadoo.fr> wrote in
news:42543177$0$11698$8fcfb975@news.wanadoo.fr:
Bonjour,
Attente->Add(BDD->Execute_Query(.....));
Mais je pourrais aussi faire:
Attente->Add(toto->OnSenFout(...));
A moins que je n'ai pas compris ta problématique,tu n'as pas besoin de
pointeur de fonction là.
N'importe quel fonction (globale ou membre de classe) convient si elle
renvoie un AnsiString .
là, Add(const AnsiString & query), c'est pour l'exemple...
je voudrais que Add(...) puisse pointer vers une fonction, peut-importe
laquelle, et que cette fonction soit exécutée quand le Timer le décide...
"Ahmed MOHAMED ALI" wrote in news:42543177$0$11698$:
Bonjour,
Attente->Add(BDD->Execute_Query(.....));
Mais je pourrais aussi faire:
Attente->Add(toto->OnSenFout(...));
A moins que je n'ai pas compris ta problématique,tu n'as pas besoin de pointeur de fonction là. N'importe quel fonction (globale ou membre de classe) convient si elle renvoie un AnsiString .
là, Add(const AnsiString & query), c'est pour l'exemple...
je voudrais que Add(...) puisse pointer vers une fonction, peut-importe laquelle, et que cette fonction soit exécutée quand le Timer le décide...
kanze
Michael wrote:
j'ai la classe suivante, qui me sert à étaler dans le temps une succession de requêtes à une base de données. (Tant qu'il y a des requêtes dans liste_attente, le Timer tourne, sinon tout se met en pause)
Donc là c'est une utilisation très spécialisée, puisque je passe la requête à Add, qui s'occupe du reste...
Comment je peux rendre cette classe plus générique, donc Comment je peux faire pour appeller n'importe quelle fonction dans Attente::Add()???
La solution la plus simple, c'est d'utiliser un objet fonctionnel polymorphique. Avec le polymorphisme dynamique, on définit une classe de base, genre :
Ceci suppose une régistration par l'objet concerné pour l'évenemment.
Par exemple dans le code j'aurais:
Attente->Add(BDD->Execute_Query(.....));
Mais je pourrais aussi faire:
Attente->Add(toto->OnSenFout(...));
J'espère avoir été clair!
Si on veut pouvoir appeler une fonction arbitraire, dans une classe arbitraire, il faudrait se servir d'une intermédiaire (modèle de conception adaptateur). Pour ça, on pourrait se servir d'un template :
template< typename T > class ConcreteCallback : public Callback { public: explicit ConcreteCallback( T* object, void (T::*f)( std::string const& ) ) : myObject( object ) , myF( f ) ; { }
template< typename T > std::auto_ptr< Callback > getCallback( T* object, void (T::*f)( std::string const& ) ) { return std::auto_ptr< T >( new ConcreteCallback< T >( object, f ) ) ; }
-- James Kanze GABI Software Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Michael wrote:
j'ai la classe suivante, qui me sert à étaler dans le temps
une succession de requêtes à une base de données. (Tant qu'il
y a des requêtes dans liste_attente, le Timer tourne, sinon
tout se met en pause)
Donc là c'est une utilisation très spécialisée, puisque je
passe la requête à Add, qui s'occupe du reste...
Comment je peux rendre cette classe plus générique, donc
Comment je peux faire pour appeller n'importe quelle fonction
dans Attente::Add()???
La solution la plus simple, c'est d'utiliser un objet
fonctionnel polymorphique. Avec le polymorphisme dynamique, on
définit une classe de base, genre :
Ceci suppose une régistration par l'objet concerné pour
l'évenemment.
Par exemple dans le code j'aurais:
Attente->Add(BDD->Execute_Query(.....));
Mais je pourrais aussi faire:
Attente->Add(toto->OnSenFout(...));
J'espère avoir été clair!
Si on veut pouvoir appeler une fonction arbitraire, dans une
classe arbitraire, il faudrait se servir d'une intermédiaire
(modèle de conception adaptateur). Pour ça, on pourrait se
servir d'un template :
template< typename T >
class ConcreteCallback : public Callback
{
public:
explicit ConcreteCallback(
T* object,
void (T::*f)( std::string const& ) )
: myObject( object )
, myF( f ) ;
{
}
j'ai la classe suivante, qui me sert à étaler dans le temps une succession de requêtes à une base de données. (Tant qu'il y a des requêtes dans liste_attente, le Timer tourne, sinon tout se met en pause)
Donc là c'est une utilisation très spécialisée, puisque je passe la requête à Add, qui s'occupe du reste...
Comment je peux rendre cette classe plus générique, donc Comment je peux faire pour appeller n'importe quelle fonction dans Attente::Add()???
La solution la plus simple, c'est d'utiliser un objet fonctionnel polymorphique. Avec le polymorphisme dynamique, on définit une classe de base, genre :
Ceci suppose une régistration par l'objet concerné pour l'évenemment.
Par exemple dans le code j'aurais:
Attente->Add(BDD->Execute_Query(.....));
Mais je pourrais aussi faire:
Attente->Add(toto->OnSenFout(...));
J'espère avoir été clair!
Si on veut pouvoir appeler une fonction arbitraire, dans une classe arbitraire, il faudrait se servir d'une intermédiaire (modèle de conception adaptateur). Pour ça, on pourrait se servir d'un template :
template< typename T > class ConcreteCallback : public Callback { public: explicit ConcreteCallback( T* object, void (T::*f)( std::string const& ) ) : myObject( object ) , myF( f ) ; { }
template< typename T > std::auto_ptr< Callback > getCallback( T* object, void (T::*f)( std::string const& ) ) { return std::auto_ptr< T >( new ConcreteCallback< T >( object, f ) ) ; }
Je suis désolé, mais je dois t'avouer que je ne comprends pas ton code, et je ne vois pas comment je peux l'utiliser dans mon cas...
Franck Branjonneau
Michael écrivait:
James
Tu as oublié la classe abstraite Callback.
template< typename T > class ConcreteCallback : public Callback { } ;
template< typename T > std::auto_ptr< Callback > getCallback( T* object, void (T::*f)( std::string const& ) ) { return std::auto_ptr< T >( new ConcreteCallback< T >( object, f ) ) ; }
Je suis désolé, mais je dois t'avouer que je ne comprends pas ton code, et je ne vois pas comment je peux l'utiliser dans mon cas...
La fonction getCallback construit dans le tas un ConcreteCallback<> que tu manipules avec un pointeur sur Callback. Pour s'assurer de sa destruction, il est encapsulé dans un std::auto_ptr.
Tu n'en as, a priori, pas besoin si tu le manipules dans ta classe Attente :
class Attente { private: // ... std::queue<Callback *> liste_attente;
// Do something with s. std::cout << s << "n"; } };
// ... Attente attente;
Foo foo; attente.add(foo, &Foo::bar);
Et attente.use() execute foo.bar("Something usefull"). -- Franck Branjonneau
Michael <michael_delva.enlever@hotmail.com> écrivait:
James
Tu as oublié la classe abstraite Callback.
template< typename T >
class ConcreteCallback : public Callback
{
} ;
template< typename T >
std::auto_ptr< Callback >
getCallback( T* object, void (T::*f)( std::string const& ) )
{
return std::auto_ptr< T >(
new ConcreteCallback< T >( object, f ) ) ;
}
Je suis désolé, mais je dois t'avouer que je ne comprends pas ton code, et
je ne vois pas comment je peux l'utiliser dans mon cas...
La fonction getCallback construit dans le tas un ConcreteCallback<>
que tu manipules avec un pointeur sur Callback. Pour s'assurer de sa
destruction, il est encapsulé dans un std::auto_ptr.
Tu n'en as, a priori, pas besoin si tu le manipules dans ta classe
Attente :
class Attente {
private:
// ...
std::queue<Callback *> liste_attente;
template< typename T > class ConcreteCallback : public Callback { } ;
template< typename T > std::auto_ptr< Callback > getCallback( T* object, void (T::*f)( std::string const& ) ) { return std::auto_ptr< T >( new ConcreteCallback< T >( object, f ) ) ; }
Je suis désolé, mais je dois t'avouer que je ne comprends pas ton code, et je ne vois pas comment je peux l'utiliser dans mon cas...
La fonction getCallback construit dans le tas un ConcreteCallback<> que tu manipules avec un pointeur sur Callback. Pour s'assurer de sa destruction, il est encapsulé dans un std::auto_ptr.
Tu n'en as, a priori, pas besoin si tu le manipules dans ta classe Attente :
class Attente { private: // ... std::queue<Callback *> liste_attente;
// Do something with s. std::cout << s << "n"; } };
// ... Attente attente;
Foo foo; attente.add(foo, &Foo::bar);
Et attente.use() execute foo.bar("Something usefull"). -- Franck Branjonneau
James Kanze
Franck Branjonneau wrote:
Michael écrivait:
Tu as oublié la classe abstraite Callback.
Qui est évidemment la partie la plus importante. La reste, c'est un exemple d'une façon (pas la seule) de s'en servir.
template< typename T > class ConcreteCallback : public Callback { } ;
template< typename T > std::auto_ptr< Callback > getCallback( T* object, void (T::*f)( std::string const& ) ) { return std::auto_ptr< T >( new ConcreteCallback< T >( object, f ) ) ; }
Je suis désolé, mais je dois t'avouer que je ne comprends pas ton code, et je ne vois pas comment je peux l'utiliser dans mon cas...
Il y a effectivement plusieurs « astuces » là-dedans. Rien d'essentiel, mais des choses qui facilitent l'utilisation par la suite, et font partie des idiomes du C++ moderne.
L'essentiel, c'est toujours que tu définis une interface Callback, que le générateur d'évenemments appelle la fonction virtuelle de l'interface, et que tu en dérives une classe qui fait ce que tu veux. Puisque tu as parlé (vaguement) d'appeler des fonctions membre d'un nom arbitraire dans une classe arbitraire, j'ai proposé le template comme classe dérivée : tu donnes la classe ciblée comme paramètre de template, et la fonction membre comme paramètre du constructeur, et il fait la reste. (On aurait aussi pu lui donner la fonction membre comme paramètre de template.)
Mais enfin, c'est parfois pénible d'avoir à écrire ConcreteCallback< MaClasse > partout. D'où la fonction templatée getCallback. Parce qu'en C++, il y a une différence importante entre les templates de classe et les templates de fonction : le compilateur déduit automatiquement les paramètres (quand il peut) des templates de fonction. Donc, à la place d'écrire :
new ConcreteCallback< MaClasse >( this, &MaClasse::maFonction )
on peut écrire :
getCallback( this, &MaClasse::maFonction ) ;
C'est une petite simplification. (Vraiment petite dans ce cas-ci, parce qu'il faut nommer la classe quand même quand on prend l'adresse de la fonction membre.)
La fonction getCallback construit dans le tas un ConcreteCallback<> que tu manipules avec un pointeur sur Callback. Pour s'assurer de sa destruction, il est encapsulé dans un std::auto_ptr.
Tu n'en as, a priori, pas besoin si tu le manipules dans ta classe Attente :
C'est effectivement une solution assez simple aussi. Déclarer le ConcreteCallback comme membre. Dans bien des cas, même, la solution la plus simple serait d'hériter directement de Callback. Ces solutions sont en fait plus simple que la solution que j'ai proposé, mais sont potentiellement moins souple. Telle qu'on a écrire Callback, on ne pert pas beaucoup en lui faisant un membre -- mais évidemment, on ne peut pas le faire avec des classes déjà existantes, qu'on ne peut pas facilement modifier. Dans une implémentation alternative de Callback, en revanche, c'est le constructeur de la classe Callback qui fait la régistration, et le destructeur qui fait la dérégistration ; une chose de moins à laquelle l'utilisateur doit penser, mais du coup, la durée de la régistration est liée à la durée de vie de l'objet Callback, et il devient préférable de la séparer de la durée de vie de l'objet concerné.
Et l'héritage direct introduit en plus la contrainte que la classe ne peut implémenter qu'un seul callback.
-- James Kanze mailto: Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 pl. Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34
Franck Branjonneau wrote:
Michael <michael_delva.enlever@hotmail.com> écrivait:
Tu as oublié la classe abstraite Callback.
Qui est évidemment la partie la plus importante. La reste, c'est
un exemple d'une façon (pas la seule) de s'en servir.
template< typename T >
class ConcreteCallback : public Callback
{
} ;
template< typename T >
std::auto_ptr< Callback >
getCallback( T* object, void (T::*f)( std::string const& ) )
{
return std::auto_ptr< T >(
new ConcreteCallback< T >( object, f ) ) ;
}
Je suis désolé, mais je dois t'avouer que je ne comprends pas
ton code, et je ne vois pas comment je peux l'utiliser dans
mon cas...
Il y a effectivement plusieurs « astuces » là-dedans. Rien
d'essentiel, mais des choses qui facilitent l'utilisation par la
suite, et font partie des idiomes du C++ moderne.
L'essentiel, c'est toujours que tu définis une interface
Callback, que le générateur d'évenemments appelle la fonction
virtuelle de l'interface, et que tu en dérives une classe qui
fait ce que tu veux. Puisque tu as parlé (vaguement) d'appeler
des fonctions membre d'un nom arbitraire dans une classe
arbitraire, j'ai proposé le template comme classe dérivée : tu
donnes la classe ciblée comme paramètre de template, et la
fonction membre comme paramètre du constructeur, et il fait la
reste. (On aurait aussi pu lui donner la fonction membre comme
paramètre de template.)
Mais enfin, c'est parfois pénible d'avoir à écrire
ConcreteCallback< MaClasse > partout. D'où la fonction templatée
getCallback. Parce qu'en C++, il y a une différence importante
entre les templates de classe et les templates de fonction : le
compilateur déduit automatiquement les paramètres (quand il
peut) des templates de fonction. Donc, à la place d'écrire :
new ConcreteCallback< MaClasse >( this, &MaClasse::maFonction )
on peut écrire :
getCallback( this, &MaClasse::maFonction ) ;
C'est une petite simplification. (Vraiment petite dans ce
cas-ci, parce qu'il faut nommer la classe quand même quand on
prend l'adresse de la fonction membre.)
La fonction getCallback construit dans le tas un
ConcreteCallback<> que tu manipules avec un pointeur sur
Callback. Pour s'assurer de sa destruction, il est encapsulé
dans un std::auto_ptr.
Tu n'en as, a priori, pas besoin si tu le manipules dans ta
classe Attente :
C'est effectivement une solution assez simple aussi. Déclarer le
ConcreteCallback comme membre. Dans bien des cas, même, la
solution la plus simple serait d'hériter directement de
Callback. Ces solutions sont en fait plus simple que la solution
que j'ai proposé, mais sont potentiellement moins souple. Telle
qu'on a écrire Callback, on ne pert pas beaucoup en lui faisant
un membre -- mais évidemment, on ne peut pas le faire avec des
classes déjà existantes, qu'on ne peut pas facilement modifier.
Dans une implémentation alternative de Callback, en revanche,
c'est le constructeur de la classe Callback qui fait la
régistration, et le destructeur qui fait la dérégistration ; une
chose de moins à laquelle l'utilisateur doit penser, mais du
coup, la durée de la régistration est liée à la durée de vie de
l'objet Callback, et il devient préférable de la séparer de la
durée de vie de l'objet concerné.
Et l'héritage direct introduit en plus la contrainte que la
classe ne peut implémenter qu'un seul callback.
--
James Kanze mailto: james.kanze@free.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 pl. Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34
Qui est évidemment la partie la plus importante. La reste, c'est un exemple d'une façon (pas la seule) de s'en servir.
template< typename T > class ConcreteCallback : public Callback { } ;
template< typename T > std::auto_ptr< Callback > getCallback( T* object, void (T::*f)( std::string const& ) ) { return std::auto_ptr< T >( new ConcreteCallback< T >( object, f ) ) ; }
Je suis désolé, mais je dois t'avouer que je ne comprends pas ton code, et je ne vois pas comment je peux l'utiliser dans mon cas...
Il y a effectivement plusieurs « astuces » là-dedans. Rien d'essentiel, mais des choses qui facilitent l'utilisation par la suite, et font partie des idiomes du C++ moderne.
L'essentiel, c'est toujours que tu définis une interface Callback, que le générateur d'évenemments appelle la fonction virtuelle de l'interface, et que tu en dérives une classe qui fait ce que tu veux. Puisque tu as parlé (vaguement) d'appeler des fonctions membre d'un nom arbitraire dans une classe arbitraire, j'ai proposé le template comme classe dérivée : tu donnes la classe ciblée comme paramètre de template, et la fonction membre comme paramètre du constructeur, et il fait la reste. (On aurait aussi pu lui donner la fonction membre comme paramètre de template.)
Mais enfin, c'est parfois pénible d'avoir à écrire ConcreteCallback< MaClasse > partout. D'où la fonction templatée getCallback. Parce qu'en C++, il y a une différence importante entre les templates de classe et les templates de fonction : le compilateur déduit automatiquement les paramètres (quand il peut) des templates de fonction. Donc, à la place d'écrire :
new ConcreteCallback< MaClasse >( this, &MaClasse::maFonction )
on peut écrire :
getCallback( this, &MaClasse::maFonction ) ;
C'est une petite simplification. (Vraiment petite dans ce cas-ci, parce qu'il faut nommer la classe quand même quand on prend l'adresse de la fonction membre.)
La fonction getCallback construit dans le tas un ConcreteCallback<> que tu manipules avec un pointeur sur Callback. Pour s'assurer de sa destruction, il est encapsulé dans un std::auto_ptr.
Tu n'en as, a priori, pas besoin si tu le manipules dans ta classe Attente :
C'est effectivement une solution assez simple aussi. Déclarer le ConcreteCallback comme membre. Dans bien des cas, même, la solution la plus simple serait d'hériter directement de Callback. Ces solutions sont en fait plus simple que la solution que j'ai proposé, mais sont potentiellement moins souple. Telle qu'on a écrire Callback, on ne pert pas beaucoup en lui faisant un membre -- mais évidemment, on ne peut pas le faire avec des classes déjà existantes, qu'on ne peut pas facilement modifier. Dans une implémentation alternative de Callback, en revanche, c'est le constructeur de la classe Callback qui fait la régistration, et le destructeur qui fait la dérégistration ; une chose de moins à laquelle l'utilisateur doit penser, mais du coup, la durée de la régistration est liée à la durée de vie de l'objet Callback, et il devient préférable de la séparer de la durée de vie de l'objet concerné.
Et l'héritage direct introduit en plus la contrainte que la classe ne peut implémenter qu'un seul callback.
-- James Kanze mailto: Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 pl. Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34