Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Passer une fonction en argument sans tenir compte des parametres par defaut

2 réponses
Avatar
Olivier
Bonjour,

J'ai le probleme suivant :
- j'ai une classe Class1 qui contient differentes fonctions du type :
x void Class1::fonc1(float var1, float var2);
x void Class1::fonc2(float var1, float var2, float var3=10);
- j'ai une deuxieme classe Class2 dans laquelle j'ai une fonction a qui
je veux passer cette fonction en argument. J'y ai défini :
x une variable Class1 m_obj1;
x un pointeur vers une fonction void (Class1::*m_fonc)(float, float);
x une fonction pour initialiser le tout : void Class2::setFonc(Class1
obj1, void (Class1::*fonc)(float, float) ) { m_obj1=obj1 ; m_fonc=fonc;}
x une fonction pour faire ce que je veux : void
Class2::appliquerFonc(float var1, float var2) {(*m_obj1.*m_fonc)(var1,
var2);};

L'idée etant que je puisse appeler des choses sur Class2 via
"appliquerFonc" en pouvant interchanger la fonction "fonc(1 ou 2)" de
Class1.

Tout marche bien dans la limite ou mes fonctions fonc1 et fonc2 de
Class1 ont seulement deux parametres.

Neanmoins, comme je l'ai ecrit ci-dessus, j'aimerais pouvoir faire la
meme chose avec une fonction comme fonc2 qui a 3 parametres mais
seulement 2 obligatoires (le troisieme ayant une valeur par defaut).

Je n'ai pas du tout trouvé comment faire.
Pourriez-vous s'il-vous-plait m'aider ?

Merci, Olivier.

2 réponses

Avatar
James Kanze
On Feb 25, 11:45 am, Olivier

wrote:

J'ai le probleme suivant :
- j'ai une classe Class1 qui contient differentes fonctions du ty pe :
x void Class1::fonc1(float var1, float var2);
x void Class1::fonc2(float var1, float var2, float var3 );
- j'ai une deuxieme classe Class2 dans laquelle j'ai une fonction a qui
je veux passer cette fonction en argument. J'y ai d fini :
x une variable Class1 m_obj1;
x un pointeur vers une fonction void (Class1::*m_fonc)(fl oat, float);
x une fonction pour initialiser le tout : void Class2::se tFonc(Class1
obj1, void (Class1::*fonc)(float, float) ) { m_obj1=obj1 ; m_fonc=fon c;}
x une fonction pour faire ce que je veux : void
Class2::appliquerFonc(float var1, float var2) {(*m_obj1.*m_fonc)(var1,
var2);};

L'id e etant que je puisse appeler des choses sur Class2 via
"appliquerFonc" en pouvant interchanger la fonction "fonc(1 ou 2)" de
Class1.

Tout marche bien dans la limite ou mes fonctions fonc1 et fonc2 de
Class1 ont seulement deux parametres.

Neanmoins, comme je l'ai ecrit ci-dessus, j'aimerais pouvoir faire la
meme chose avec une fonction comme fonc2 qui a 3 parametres mais
seulement 2 obligatoires (le troisieme ayant une valeur par defaut).

Je n'ai pas du tout trouv comment faire.
Pourriez-vous s'il-vous-plait m'aider ?



Le plus simple, c'est simplement de remplacer la fonction avec
de paramètres avec des valeurs par defaut par des fonctions
surchargées. Le problème, sinon, c'est au point de l'appel, il
faut que le compilateur passe trois paramètres réels à la fonc2,
alors que selon le type du pointeur à fonction qu'il a, il croit
que deux suffisent.

Sinon, il faut utiliser une classe de délégation templatée.
Quelque chose du genre:

class AppelVersClass1Abstraite
{
public:
virtual ~AppelVersClass1Abstrait() {}
virtual void appel(Class1* instance, float var1, float var2)
const = 0
};

template <typename PFM>
class AppelVersClass1 : public AppelVersClass1Abstraite
{
PFM m_func;
public:
AppelVersClass1(PFM func) : m_func(func) {}
virtual void appel(Class1* instance, float var1, float var2)
const
{
(instance->*m_func)(var1, var2);
}
};
// Et pour profiter de l'induction des types...
template <typename PFM>
AppelVersClass1<PFM>*
appelVersClass1(PFM func)
{
return new AppelVersClass1(func);
}

Ce qui introduit un léger problème de gestion de la mémoire.
(C'est un cas où je conseillerais boost::shared_ptr. Puisque
AppelVersClass1 ne contient pas de pointeurs, il n'y a pas de
risque de cycles.)

--
James Kanze
Avatar
Olivier
Bonjour,

Merci pour cette réponse !

J'ai finalement choisi la facilité en surchargeant ma fonction
Class1::fonc2 par une fonction a deux parametres... (au depart je ne
voulais pas toucher a la definition de Class1 mais bon...)

Merci encore, Olivier.


Le 25/02/2011 18:37, James Kanze a écrit :
On Feb 25, 11:45 am, Olivier

wrote:

J'ai le probleme suivant :
- j'ai une classe Class1 qui contient differentes fonctions du type :
x void Class1::fonc1(float var1, float var2);
x void Class1::fonc2(float var1, float var2, float var3);
- j'ai une deuxieme classe Class2 dans laquelle j'ai une fonction a qui
je veux passer cette fonction en argument. J'y ai d fini :
x une variable Class1 m_obj1;
x un pointeur vers une fonction void (Class1::*m_fonc)(float, float);
x une fonction pour initialiser le tout : void Class2::setFonc(Class1
obj1, void (Class1::*fonc)(float, float) ) { m_obj1=obj1 ; m_fonc=fonc;}
x une fonction pour faire ce que je veux : void
Class2::appliquerFonc(float var1, float var2) {(*m_obj1.*m_fonc)(var1,
var2);};



L'id e etant que je puisse appeler des choses sur Class2 via
"appliquerFonc" en pouvant interchanger la fonction "fonc(1 ou 2)" de
Class1.



Tout marche bien dans la limite ou mes fonctions fonc1 et fonc2 de
Class1 ont seulement deux parametres.



Neanmoins, comme je l'ai ecrit ci-dessus, j'aimerais pouvoir faire la
meme chose avec une fonction comme fonc2 qui a 3 parametres mais
seulement 2 obligatoires (le troisieme ayant une valeur par defaut).



Je n'ai pas du tout trouv comment faire.
Pourriez-vous s'il-vous-plait m'aider ?



Le plus simple, c'est simplement de remplacer la fonction avec
de paramètres avec des valeurs par defaut par des fonctions
surchargées. Le problème, sinon, c'est au point de l'appel, il
faut que le compilateur passe trois paramètres réels à la fonc2,
alors que selon le type du pointeur à fonction qu'il a, il croit
que deux suffisent.

Sinon, il faut utiliser une classe de délégation templatée.
Quelque chose du genre:

class AppelVersClass1Abstraite
{
public:
virtual ~AppelVersClass1Abstrait() {}
virtual void appel(Class1* instance, float var1, float var2)
const = 0
};

template<typename PFM>
class AppelVersClass1 : public AppelVersClass1Abstraite
{
PFM m_func;
public:
AppelVersClass1(PFM func) : m_func(func) {}
virtual void appel(Class1* instance, float var1, float var2)
const
{
(instance->*m_func)(var1, var2);
}
};
// Et pour profiter de l'induction des types...
template<typename PFM>
AppelVersClass1<PFM>*
appelVersClass1(PFM func)
{
return new AppelVersClass1(func);
}

Ce qui introduit un léger problème de gestion de la mémoire.
(C'est un cas où je conseillerais boost::shared_ptr. Puisque
AppelVersClass1 ne contient pas de pointeurs, il n'y a pas de
risque de cycles.)

--
James Kanze