OVH Cloud OVH Cloud

pointeur de fonction?

10 réponses
Avatar
3dsman
Salut!

Je cherche a faire un truc mais je ne vois pas trop comment m'y
prendre:

j'ai deux classes A et B

class A
{
private:
B* pB

public:
A(){
pB = new B();
}
fonctionA();
}

class B
{
private:

public:

fonctionB(){ truc; truc; truc; fonctionA(); truc; truc;};
}

voila en fait le but c'est que je puisse appeller une fonction de la
classe A a partir d'une instance la classe B construite das la classe A
Je cherche a pouvoir créer cette classe B a partir de n'importe quelle
classe ( j'aurais d'autres classes que la A qui construiront des
instances de la B )

J'avais penssé aux pointeurs de fonction mais apres plusieurs essais je
me suis rendu compte que j'y pigeais que dale :-) donc si une ame
charitable voulais bien me passer un coup de main je lui en serrait
tres reconaissant :-)

--
Ceci est une signature automatique de MesNews.
Site : http://mesnews.no-ip.com

10 réponses

Avatar
Jean-Marc Bourguet
3dsman writes:

voila en fait le but c'est que je puisse appeller une fonction de la
classe A a partir d'une instance la classe B construite das la
classe A Je cherche a pouvoir créer cette classe B a partir de
n'importe quelle classe ( j'aurais d'autres classes que la A qui
construiront des instances de la B )


Et que veux-tu faire quand les instances de B auront ete cree en
dehors d'un A?

Avant de chercher une solution a un probleme, il faut peut-etre penser
a le poser completement..

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

Avatar
Christophe Lephay
3dsman wrote:
voila en fait le but c'est que je puisse appeller une fonction de la
classe A a partir d'une instance la classe B construite das la classe
A Je cherche a pouvoir créer cette classe B a partir de n'importe
quelle classe ( j'aurais d'autres classes que la A qui construiront
des instances de la B )


Tu peux faire de ta fonction membre dans A une fonction membre statique
(qui peut être appelée sans instance de A) :

class A
{
public:
static void fonctionA();
};

class B
{
void fonctionB() { A::fonctionA(); }
};

Si seule la classe B doit pouvoir appeler cette fonction, tu la mets en
private dans A et tu fais de B une classe friend.


Si fonctionA doit être appelée depuis une instance particulière de A, il
faut indiquer laquelle à ta classe B, soit en fournissant l'objet, pointeur
ou reférence correspondant à fonctionB (si l'objet peut varier d'un appel à
l'autre) soit en le transmettant à B au niveau du constructeur :

class B
{
void fonctionB( A * theA ) { theA->fonctionA(); }
};

ou encore :

class B
{
B( A * someA ) : myA( someA ) {}
B() : myA( new A ) {} // une variante ou la classe B construit elle même un
objet A
void fonctionB() { myA->fonctionA(); }

A * myA;
};

Eventuellement, tu peux créer un objet temporaire de type A pour l'appel de
ta fonction (pour l'idiome RAII - Resource Acquisition Is Initialisation,
qui offre quelques garanties sur les acquisitions et libérations de
ressources :

class B
{
void fonctionB() { A temp; temp.fonctionA(); } // ou encore A().fonctionA();
};


Mais comme le disait Jean-Marc, il faut voir plus précisément ton problème
pour déterminer quelle est la meilleure solution (dès que plusieurs classes
doivent collaborer entre elles, le problème se rapproche plus du design que
de simples fonctionnalités ou howtos C++).

Chris

Avatar
3dsman
3dsman writes:

voila en fait le but c'est que je puisse appeller une fonction de la
classe A a partir d'une instance la classe B construite das la
classe A Je cherche a pouvoir créer cette classe B a partir de
n'importe quelle classe ( j'aurais d'autres classes que la A qui
construiront des instances de la B )


Et que veux-tu faire quand les instances de B auront ete cree en
dehors d'un A?

Avant de chercher une solution a un probleme, il faut peut-etre penser
a le poser completement..

A+


ben en fait ce que je voudrais c'est que la classe B lance une fonction
(qu'on lui donne)(si on ne lui donne pas elle ne lance rien) de la
classe A ou de n'importe quelle autre classe.

en gros l'idée c'est:

je crée une instance de A.
cette instance de A crée une instance de B dans son constructeur
J'aimerais que A puisse donner a B la possibilité d'utiliser une de ses
fonctions (a A)

--
Ceci est une signature automatique de MesNews.
Site : http://mesnews.no-ip.com


Avatar
drkm
3dsman writes:


Avant de chercher une solution a un probleme, il faut peut-etre penser
a le poser completement..


en gros l'idée c'est:

je crée une instance de A.
cette instance de A crée une instance de B dans son constructeur
J'aimerais que A puisse donner a B la possibilité d'utiliser une de ses
fonctions (a A)


Ceci pourrait t'intéresser :

#include <iostream>
#include <boost/bind.hpp>
#include <boost/function.hpp>

class C {
public:
C() {
}
C( boost::function< void () > func )
: myFunc( func ) {
}
void action() {
myFunc() ;
}
private:
boost::function< void () >
myFunc ;
} ;

void freeFun() {
std::cout << "in freeFun()" << std::endl ;
}

class Client {
public:
Client() {
myC = new C( boost::bind( & Client::fun , this ) ) ;
}
void fun() {
std::cout << "in Client::fun()" << std::endl ;
}
void action() {
myC->action() ;
}
private:
C * myC ;
} ;

int main() {
{
C c( & freeFun ) ;
c.action() ;
}
{
Client c ;
c.fun() ;
}
}

Mais je ne sais pas si cela peut s'appliquer tel quel à ton
problème, ne le connaissant pas.

--drkm


Avatar
drkm
drkm writes:

{
Client c ;
c.fun() ;
}


« c.action() » serait ici plus intéressant ;-).

--drkm

Avatar
drkm
drkm writes:

Ceci pourrait t'intéresser :


Oops. J'ai posté trop vite, avant de finir le support du caractère
optionel du foncteur. Il manque le test sur myFunc dans C::action().
Donc finalement :

#include <iostream>
#include <boost/bind.hpp>
#include <boost/function.hpp>

class C {
public:
C() {
}
C( boost::function< void () > func )
: myFunc( func ) {
}
void action() {
if ( myFunc ) {
myFunc() ;
}
}
private:
boost::function< void () >
myFunc ;
} ;

void freeFun() {
std::cout << "in freeFun()" << std::endl ;
}

class Client {
public:
Client() {
myC = new C( boost::bind( & Client::fun , this ) ) ;
}
void fun() {
std::cout << "in Client::fun()" << std::endl ;
}
void action() {
myC->action() ;
}
private:
C * myC ;
} ;

int main() {
{
C c ;
c.action() ;
}
{
C c( & freeFun ) ;
c.action() ;
}
{
Client c ;
c.action() ;
}
}

--drkm

Avatar
3dsman
mais dans cet exemple la classe client ne pour fontionner qu'avec la
classe C???
Je me trompe?

Et heu c obligé d'utiliser boost ou ce systeme est totalement
independant?

--
Ceci est une signature automatique de MesNews.
Site : http://mesnews.no-ip.com
Avatar
Jean-Marc Bourguet
3dsman writes:

ben en fait ce que je voudrais c'est que la classe B lance
une fonction (qu'on lui donne)(si on ne lui donne pas elle
ne lance rien) de la classe A ou de n'importe quelle autre
classe.


Ah, c'est déjà bien différent de ce que tu disais.

en gros l'idée c'est:

je crée une instance de A. cette instance de A crée une
instance de B dans son constructeur J'aimerais que A
puisse donner a B la possibilité d'utiliser une de ses
fonctions (a A)


Regarde les signaux. Il y a au moins deux implémentations
disponibles (sig++ et chez boost) et on a discuté de ça ici
dans le passé.

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

Avatar
drkm
3dsman writes:

mais dans cet exemple la classe client ne pour fontionner qu'avec la
classe C???


Pour faire le lien avec ton exemple initial, remplace C par B, et
Client par A. Tu veux que le constructeur de A crée une instance de
B. Donc oui, A (Client) dépend de B (C).

--drkm

Avatar
James Kanze
3dsman writes:

|> Je cherche a faire un truc mais je ne vois pas trop comment m'y
|> prendre:

|> j'ai deux classes A et B

|> class A
|> {
|> private:
|> B* pB

|> public:
|> A(){
|> pB = new B();
|> }
|> fonctionA();
|> }

|> class B
|> {
|> private:

|> public:

|> fonctionB(){ truc; truc; truc; fonctionA(); truc; truc;};
|> }

|> voila en fait le but c'est que je puisse appeller une fonction de la
|> classe A a partir d'une instance la classe B construite das la
|> classe A Je cherche a pouvoir créer cette classe B a partir de
|> n'importe quelle classe ( j'aurais d'autres classes que la A qui
|> construiront des instances de la B )

Pour donner la meilleur solution, il faudrait qu'on sache le problème,
et non simplement une esquisse d'une solution qui ne marche pas. Mais
assez souvent, dans ce genre de chose, on définit une interface de
callback, dont on passe une instance au constructeur de B. À la suite,
ou bien, A implémente cette interface, ou bien, on y définit une petite
classe de passerelle qui l'implémente. (La passerelle est nettement plus
de travaille, mais est souvent plus propre.)

Dans tous les cas, il faut gérer la durée de vie des dérivées de
l'interface. Avec la passerelle, par exemple, il est en général loisible
que le destructeur de B detruit la passerelle dans son destructeur ; si
c'est A qui implémente l'interface directement, en revanche, c'est
prèsque jamais une bonne idée. Si, quand tu écris B, tu veux laisser le
choix libre à celui qui implémente A, il faut passer un paramètre on
plus au constructeur, qui indique si on a la propriété ou non.

Ce qui donne, pour B, quelque chose du genre :

class B
{
public:
class Callback
{
virtual ~Callback() {}
virtual void whatever() = 0 ;
} ;

B( Callback* callback, bool deleteWhenFinished )
: myCallback( callback )
, myDeleteWhenFinished( deleteWhenFinished )
{
}

~B()
{
if ( myDeleteWhenFinished ) {
delete callback ;
}
}

void functionB()
{
callback->whatever() ;
}
private:
Callback* myCallback ;
bool myDeleteWhenFinished ;
} ;

Et dans A, soit :

A::A()
{
pB = new B( this, false ) ;
}

(A dérive directement de B::Callback), soit :

A::A()
{
pB = new B( new CallbackA( this ), true ) ;
}

(A définit une passerelle, CallbackA.)

Le modèle avec la passerelle est tellement courant en programmation OO
que Java le supporte directement dans le langage.

--
James Kanze
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34