C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Pointeur sur fonction membre

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (French)
View previous topic :: View next topic  
Author Message
Boris Sargos
Guest





PostPosted: Sat May 08, 2004 11:16 am    Post subject: Pointeur sur fonction membre Reply with quote



Salut à tous,

dans une de mes classes, j'ai besoin de stocker l'adresse d'une fonction
membre d'une autre classe. Sachant que les deux classes en question ne se
connaissent pas (et c'est important), je souhaiterais naturellement écrire
un truc du genre :


Class A {
private :
double& GetA() { return m_A; }
double m_A;
}

Class B {
public:
B(double&(*f)(void)) { GetA = f; } // Constructeur
private :
double&(*GetA)(void);
}

Mais ce code ne compile pas. Je n'ai apparamment pas le droit d'écrire un
tel truc. Je ne comprends pas pourquoi.
Quelqu'un pourrait-il m'expliquer ce qui ne va pas, et comment y palier ?

Note : j'ai également essayé avec les classes mem_fun_t et compagnie
fournies par la stl. Ca n'a pas non plus fonctionné.

Merci de votre aide.


Back to top
Michel Michaud
Guest





PostPosted: Sat May 08, 2004 11:27 am    Post subject: Re: Pointeur sur fonction membre Reply with quote



Dans news:c7ifeg$iog$1 (AT) news-reader2 (DOT) wanadoo.fr, Boris
Sargos <bsargos (AT) wanadoo (DOT) fr> a écrit :
Quote:
Salut à tous,

dans une de mes classes, j'ai besoin de stocker l'adresse d'une
fonction membre d'une autre classe. Sachant que les deux
classes en question ne se connaissent pas (et c'est important),
je souhaiterais naturellement écrire un truc du genre :


Class A {
private :
double& GetA() { return m_A; }
double m_A;
}

Class B {
public:
B(double&(*f)(void)) { GetA = f; } //
Constructeur private :
double&(*GetA)(void);
}

Mais ce code ne compile pas. Je n'ai apparamment pas le droit
d'écrire un tel truc. Je ne comprends pas pourquoi.

Un pointeur sur une fonction membre, ce n'est pas la même chose
qu'un pointeur sur une fonction. Tu ne peux pas garder l'un
dans une variable pour l'autre. Si les deux classes ne se
connaissent pas, je ne vois pas comment tu pourras faire parce
que pour déclarer le pointeur sur une fonction, il faut avoir
son type et il dépend de la classe... Je vois bien comment
recevoir le pointeur (avec une fonction template), mais je ne
vois pas comment le storer dans un variable membre d'une classe
ordinaire (on pourrait le faire avec une classe template, mais
je ne crois pas que ça soit un choix possible dans ton cas). Il
est tôt pour moi, alors peut-être que quelqu'un d'autre aura
une meilleure idée !

Que voulais-tu faire exactement ? Peut-être qu'il y a une autre
solution (je pense au pattern Visitor par exemple...).

--
Michel Michaud [email]mm (AT) gdzid (DOT) com[/email]
http://www.gdzid.com
FAQ de fr.comp.lang.c++ :
http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/



Back to top
Michel Michaud
Guest





PostPosted: Sat May 08, 2004 11:50 am    Post subject: Re: Pointeur sur fonction membre Reply with quote



Dans news:Qu3nc.100362$ZJ5.2201261 (AT) news20 (DOT) bellglobal.com, Michel
Michaud <mm (AT) gdzid (DOT) com> a écrit :
Quote:
Un pointeur sur une fonction membre, ce n'est pas la même chose
qu'un pointeur sur une fonction. Tu ne peux pas garder l'un
dans une variable pour l'autre. Si les deux classes ne se
connaissent pas, je ne vois pas comment tu pourras faire parce
que pour déclarer le pointeur sur une fonction, il faut avoir

Lire « sur une fonction MEMBRE »

Quote:
son type et il dépend de la classe...

--
Michel Michaud [email]mm (AT) gdzid (DOT) com[/email]
http://www.gdzid.com
FAQ de fr.comp.lang.c++ :
http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/


Back to top
Gregory Montoir
Guest





PostPosted: Sat May 08, 2004 1:19 pm    Post subject: Re: Pointeur sur fonction membre Reply with quote

Boris Sargos wrote:
Quote:
Salut à tous,

dans une de mes classes, j'ai besoin de stocker l'adresse d'une fonction
membre d'une autre classe. Sachant que les deux classes en question ne se
connaissent pas (et c'est important), je souhaiterais naturellement écrire
un truc du genre :
[...]
Mais ce code ne compile pas. Je n'ai apparamment pas le droit d'écrire un
tel truc. Je ne comprends pas pourquoi.
Quelqu'un pourrait-il m'expliquer ce qui ne va pas, et comment y palier ?

Ca me parait un peu bizarre ce que tu cherches a faire... Enfin, si
c'est juste un probleme de syntaxe, essaye un truc comme ca :

class A {
public:
A(double d) : d_(d) {}
double& get() { return d_; }
private:
double d_;
};

typedef double& (A::*GetDouble)();

class B {
public:
B(GetDouble gd) : gd_(gd) {}
GetDouble GetDoubleProc() { return gd_; }
private:
GetDouble gd_;
};

int main() {
A a1(3.14);
A a2(0.);
B b(&A::get);
GetDouble gd = b.GetDoubleProc();
std::cout << (a1.*gd)() << std::endl << (a2.*gd)() << std::endl;
return 0;
}

$ g++ b.cpp && a
3.14
0

En esperant que ca te fasse avancer...


Back to top
Boris Sargos
Guest





PostPosted: Sat May 08, 2004 1:46 pm    Post subject: Re: Pointeur sur fonction membre Reply with quote

Merci à vous deux pour votre aide. J'ai compris que j'ai fait une faute de
structuration, et que je n'ai pas choisi la bonne implémentation.
Je vais réfléchir à une autre solution.

Merci.


Back to top
drkm
Guest





PostPosted: Sat May 08, 2004 1:52 pm    Post subject: Re: Pointeur sur fonction membre Reply with quote

"Michel Michaud" <mm (AT) gdzid (DOT) com> writes:

Quote:
Je vois bien comment
recevoir le pointeur (avec une fonction template)

Mais si B ne connait pas A à la compilation ? Je ne suis pas
certain de voir exactement ce à quoi tu penses. Peux-tu être plus
précis, s'il te plaît ?

Il me semble que si le coup du modèle de fonction marche, un modèle
de classe imbriqué devrait convenir pour le stockage. Reste la
question de l'exécution de la fonction pointée, pour laquelle un objet
est requis.

Mais je ne vois pas bien l'intérêt de garder un pointeur sur
fonction membre d'une classe inconnue. Peux-tu (le PO) décrire plus
précisément ce que tu veux faire ?

--drkm

Back to top
drkm
Guest





PostPosted: Sat May 08, 2004 2:04 pm    Post subject: Re: Pointeur sur fonction membre Reply with quote

Gregory Montoir <g@a.b> writes:

Quote:
class A {
public:
A(double d) : d_(d) {}
double& get() { return d_; }
private:
double d_;
};

typedef double& (A::*GetDouble)();

class B {
public:
B(GetDouble gd) : gd_(gd) {}
GetDouble GetDoubleProc() { return gd_; }
private:
GetDouble gd_;
};

int main() {
A a1(3.14);
A a2(0.);
B b(&A::get);
GetDouble gd = b.GetDoubleProc();
std::cout << (a1.*gd)() << std::endl << (a2.*gd)() << std::endl;
return 0;
}

$ g++ b.cpp && a
3.14
0

En esperant que ca te fasse avancer...

Mais le PO a précisé que B ne « connait pas » A. Je ne sais pas
trop que penser à ce sujet. S'il veut dire que A n'est pas déclaré
dans l'UC où l'on utilise B, je ne vois pas comment régler son
problème.

J'ai l'impression qu'il cherche un moyen de reporter à l'exécution
la fonction membre choisie *et* le type de l'objet de cette fonction.
Un genre de template dynamique. Et là, je ne vois pas de solution ;
je pense d'ailleurs qu'il n'y en a pas.

--drkm

Back to top
Boris Sargos
Guest





PostPosted: Sat May 08, 2004 4:38 pm    Post subject: Re: Pointeur sur fonction membre Reply with quote

Merci de tenter de répondre à ma requête.


Quote:
Je vois bien comment
recevoir le pointeur (avec une fonction template)

Mais si B ne connait pas A à la compilation ? Je ne suis pas
certain de voir exactement ce à quoi tu penses. Peux-tu être plus
précis, s'il te plaît ?

En fait, vous avez raison, j'ai trop simplifié mon exemple : A connaît B,
mais B ne connaît pas A.
Pour être plus précis, B est un itérateur de A :

Class MyVector { // la classe A
public:
MyIterator begin() { return MyIterator(0, &GetValue); }
double& operator [] (int i) { return GetValue(i); }
private :
double& GetValue(int i) { return UN_DOUBLE; }
vector<double>* m_pMyTab;
}

Class MyIterator { // la classe B
public:
MyIterator (double&(*f)(void)) { ref = f; } //
Constructeur
double & operator * ( return ref(m_Current); } //
Appelle en fait MyVector::GetValue(m_Current)
MyIterator& operator ++ () { m_Current++; return *this; }
private :
double&(*ref)(void);
int m_Current;
}

Là encore, j'ai simplifié. Mais il est clair que MyIterator ne peut pas
connaître MyVector.
La fonction MyVector::GetValue(int i) renvoie un élément du tableau m_pMyTab
mais pas nécessairement le i-ème. C'est bien sûr pour cette raison que le
tout est si compliqué : je suis obligé de créer mon propre itérateur pour
tenir compte de cet index variable.
Par exemple, cela peut être :

double& GetValue(int i) {
return (*m_pMyTab)[random(m_pMyTab->size()-1];
}

Où random(int i) retourne un nombre choisi aléatoirement entre 0 et i.
J'aurais dû, alors, écrire directement la fonction GetValue dans la classe
itérateur MyIterator. Mais dans ce cas, je n'aurais pas pu en bénéficier
lors de la surcharge de [] dans la classe MyVector.

Est-ce plus clair ?
Merci.




Back to top
drkm
Guest





PostPosted: Sun May 09, 2004 12:11 am    Post subject: Re: Pointeur sur fonction membre Reply with quote

"Boris Sargos" <bsargos (AT) wanadoo (DOT) fr> writes:

Quote:
Je vois bien comment
recevoir le pointeur (avec une fonction template)

Mais si B ne connait pas A à la compilation ? Je ne suis pas
certain de voir exactement ce à quoi tu penses. Peux-tu être plus
précis, s'il te plaît ?

En fait, vous avez raison, j'ai trop simplifié mon exemple : A connaît B,
mais B ne connaît pas A.
Pour être plus précis, B est un itérateur de A :

Class MyVector { // la classe A
public:
MyIterator begin() { return MyIterator(0, &GetValue); }
^^^^^^^^^^^^


Le constructeur de MyIterator ne prend qu'un paramètre. Mais ce
n'est sans doute qu'une erreur de recopiage lors de la simplification
du code.

Quote:
double& operator [] (int i) { return GetValue(i); }
private :
double& GetValue(int i) { return UN_DOUBLE; }
vector<double>* m_pMyTab;
}

Class MyIterator { // la classe B
public:
MyIterator (double&(*f)(void)) { ref = f; } //
^^^^
Constructeur
double & operator * ( return ref(m_Current); } //
^^^^^^^^
Appelle en fait MyVector::GetValue(m_Current)
MyIterator& operator ++ () { m_Current++; return *this; }
private :
double&(*ref)(void);
^^^^


GetValue prend un entier en paramètre. La simplification, encore,
j'imagine.

Quote:
int m_Current;
}

Là encore, j'ai simplifié. Mais il est clair que MyIterator ne peut pas
connaître MyVector.

Pourquoi ? Typiquement, j'utiliserais ici un modèle de classe (si
du moins aucune subtilité ne m'a échappée).

template< class Container , typename Type >
class MyIterator
{
public:
typedef Type & ( Container::* Accessor )( int ) ;

MyIterator( Container & c , Accessor a )
 : myCont( c )
, myAccess( a )
, myIndex( some_value )
{
}

Type & operator*()
{
return myCont.*myAccess( myIndex ) ;
}

MyIterator & operator++() ;
MyIterator & operator++( int ) ;

private:
Container & myCont ;
Accessor myAccess ;
int myIndex ;
} ;

Du moins si l'on tient au pointeur sur fonction. Personnellement,
je pense qu'un paramètre template supplémemtaire pour renseigner un
foncteur serait plus souple.

template
<
class Container_t ,
typename Accessor_t = ContainerTraits< Container >::Accessor
typename Type_t = ContainerTraits< Container >::Type
Quote:

class MyIterator

{
public:
typename Container_t Container ;
typename Accessor_t Accessor ;
typename Type_t Type ;

MyIterator( Container & c )
 : myCont( c )
, myAccess( Accessor() )
{
}

MyIterator( Container & c , Accessor const & a )
 : myCont( c )
, myAccess( a )
{
}

Type & operator*()
{
return myAccess() ;
}

Type & operator->()
{
return & myAccess() ;
}

MyIterator & operator++() ; // redirection vers myAccess
MyIterator operator++( int ) ; // redirection vers myAccess

private:
Container & myCont ;
Accessor myAccess ;
} ;

Code non testé.

Quote:
La fonction MyVector::GetValue(int i) renvoie un élément du tableau m_pMyTab
mais pas nécessairement le i-ème. C'est bien sûr pour cette raison que le
tout est si compliqué : je suis obligé de créer mon propre itérateur pour
tenir compte de cet index variable.
Par exemple, cela peut être :

double& GetValue(int i) {
return (*m_pMyTab)[random(m_pMyTab->size()-1];
}

Où random(int i) retourne un nombre choisi aléatoirement entre 0 et i.
J'aurais dû, alors, écrire directement la fonction GetValue dans la classe
itérateur MyIterator. Mais dans ce cas, je n'aurais pas pu en bénéficier
lors de la surcharge de [] dans la classe MyVector.

Avec un itérateur enregistrant un foncteur, on peut facilement
encapsuler des fonctions membres du conteneur, mais aussi créer de
tous nouveaux algorithmes d'itération, à l'extérieur de la classe.

Quote:
Est-ce plus clair ?

Je pense. Mais peut-être quelque chose m'a échappé ... Notamment
la non visibilité du type de conteneur par l'itérateur.

Quote:
Merci.

Attend de voir si la réponse te convient Wink.

--drkm

Back to top
Boris Sargos
Guest





PostPosted: Sun May 09, 2004 6:49 am    Post subject: Re: Pointeur sur fonction membre Reply with quote

Ta réponse me convient parfaitement. Je te remercie d'avoir passé du temps à
la rédiger, c'est vraiment très aimable de ta part.
En ce qui me concerne, ça me semble compliqué, mais je vais bien sûr le
tester.

Quote:
Quelque chose m'a échappé ... Notamment
la non visibilité du type de conteneur par l'itérateur.

A cause des références (#include) croisées : MyVector connaît nécessairement
la définition de MyIterator parce que dans le fichier MyVector.h, j'ajoute
#include "MyIterator.h". Dans ce cas, je ne peux pas faire de même pour
MyIterator : je ne peux pas ajouter dans "MyIterator.h" la ligne "#include
MyVector.h". Et comme j'utilise des références et non pas des vecteurs comme
paramètres de mes fonctions, je ne peux pas utiliser la déclaration class
MyVector juste avant la définition de MyIterator.
De plus, il me semble qu'un itérateur doit être indépendant du conteneur,
n'est-ce pas ?

Juste une petite question, puisque tu sembles calé : as-tu déjà implémenté
une classe matrice en vue de calculs mathématiques performants ? Et dans ce
cas, si ce n'est pas trop long à décrire, quelle architecture Vector/Matrix
as-tu choisi ?

Je te remercie encore de tes réponses Smile)
Bon dimanche.
Boris.



Back to top
drkm
Guest





PostPosted: Sun May 09, 2004 11:17 am    Post subject: Re: Pointeur sur fonction membre Reply with quote

"Boris Sargos" <bsargos (AT) wanadoo (DOT) fr> writes:

Quote:
Ta réponse me convient parfaitement. Je te remercie d'avoir passé du temps à
la rédiger, c'est vraiment très aimable de ta part.

Pas de quoi.

Quote:
En ce qui me concerne, ça me semble compliqué, mais je vais bien sûr le
tester.

Ce n'est pas si compliqué, une fois qu'on l'a compris Smile. Mais
attend peut-être d'éventuelles critiques à son sujet. Je n'ai pas la
science infuse ...

Quote:
Quelque chose m'a échappé ... Notamment
la non visibilité du type de conteneur par l'itérateur.

A cause des références (#include) croisées

// MyIterator.h

template< class Container , typename Accessor >
class MyIterator
{
 ...
} ;


// MyContainer.h

#include "MyIterator.h"

template< typename Type >
class MyContainer
{
public:
typedef ... MyAccessor ;
typedef MyIterator< MyContainer , MyAccessor >
Iterator ;
 ...
} ;

[...]

Quote:
Juste une petite question, puisque tu sembles calé : as-tu déjà implémenté
une classe matrice en vue de calculs mathématiques performants ? Et dans ce
cas, si ce n'est pas trop long à décrire, quelle architecture Vector/Matrix
as-tu choisi ?

Moi, jamais. Mais je connais quelqu'un Wink. D'autres sont plus
adptes ici pour te répondre.

Quote:
Je te remercie encore de tes réponses Smile)

Merci Wink.

Quote:
Bon dimanche.

Vous-mêmes.

--drkm

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (French) All times are GMT
Page 1 of 1

 
Jump to:  
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


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.