Bonjour,
J'essaye de réaliser une fonction prenant en paramètre un pointeur sur une autre fonction.
Pour illustrer mon problème, j'ai créé une classe A qui gère un string, une classe B qui gère une collection de A (en utilisant les vectors) et une procédure doStuff qui créé un iterator parcourant la collection et applique la fonction passée en paramètre. Pour le bien de cet exemple, j'ai écris deux fonctions membres dans B qui mettent respectivement un string en majuscule et en minuscule.
Le but attendu : Dans le main, je peux un coup appeler doStuff(stringToLowerCase) et il va afficher "hello world", puis doStuff(stringToUpperCase) et il affichera "HELLO WORLD".
Mon implémentation est la suivante :
Je définis un type fctDoStuffOnList dans B, c'est un type de fonction qui prend en paramètre un string &.
B dispose aussi des deux fonctions stringToLowerCase(string &) et stringToUppercase(string &), que je suis censé passer en paramètre dans main à l'appel de doStuff(...).
Mon problème est que dans le corps de doStuff, à l'endoit "fct(*it)" j'obtiens une erreur "l'expression qui précède les parenthèses de l'appel apparent doit avoir le type de fonction (pointeur-à-)".
J'ai un peu d'expérience en ce qui concerne les pointeurs de fonctions, mais je n'avais jamais essayé d'utiliser des pointeurs sur des fonctions membres non-statiques.
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
class A {
public:
// Classe exemple pour symboliser le fait que je souhaite utiliser
// une classe que j'ai fait moi-même et pas tout simplement un vector<string> par exemple
std::string name;
A(const std::string &name) : name(name) {}
virtual ~A() {}
};
class B {
std::vector<A> listB;
public:
// Je mets "hello world" dans mon itérateur
B() {
this->listB.push_back(A("hello"));
this->listB.push_back(A(" "));
this->listB.push_back(A("world"));
}
// Procédure qui prend en paramètre un string et le met en majuscule, la question n'est pas de vérifier qu'elle fonctionne
void stringToUpperCase(std::string & str) {
std::transform(str.begin(), str.end(), str.begin(), ::toupper);
}
// Procédure qui prend en paramètre un string et le met en minuscule, la question n'est pas de vérifier qu'elle fonctionne
void stringToLowerCase(std::string & str) {
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
}
// Je définis ici le type fctDoStuffOnList qui prend en paramètre un string &, qui ne retourne rien (void)
typedef void(B::*fctDoStuffOnList)(std::string &);
// Procédure qui parcourt le vector et applique à chaque objet un traitement (donné en paramètre)
// Ici, fct est un pointeur de fonction
void doStuff(fctDoStuffOnList fct) {
std::vector<A>::iterator it;
for (it = listB.begin(); it < listB.end(); it++) {
// La ligne suivante me fait une erreur :
// "l'expression qui précède les parenthèses de l'appel apparent doit avoir le type de fonction (pointeur-à-)"
[color=red](this->*[/color]fct[color=red])[/color](it->name);
// J'affiche l'objet traité
std::cout << it->name;
}
std::cout << std::endl;
}
virtual ~B() {}
};
int main() {
B test;
// Appel à test.doStuff avec en paramètre B::stringToUpperCase
test.doStuff(&B::stringToUpperCase);
system("pause");
exit(0);
}
Je ne comprends pas comment corriger cette erreur. J'ai déjà fait des pointeurs sur des fonctions non membres, du style :
#include <math.h>
#include <iostream>
double racine(const double x) { return sqrt(x); }
double carre(const double x) { return x * x; }
// Création d'un type fonction qui retourne un double et qui prend en paramètre un double
typedef double(*calcul)(const double);
double calculer(const double & nb, calcul fonction) {
return fonction(nb);
}
int main() {
double neuf = 9.;
std::cout << "racine : " << calculer(neuf, racine) << std::endl
<< "carre : " << calculer(neuf, carre) << std::endl;
system("pause");
exit(0);
}
Toute aide est bienvenue !
----------------------------------------
Edit : J'ai fini par trouver la solution tout seul peu de temps après avoir posté ce pavé.
Je l'ai mis en rouge pour indiquer ce qu'il me manquait.
Je compte laisser ce post en ligne à titre d'exemple (sauf si un modérateur me demande de l'enlever bien sûr).
De ce que j'ai compris, l'appel à "fct" devait se faire par un pointeur sur une classe. On s'en fiche de la valeur de ce pointeur, tout ce qui compte est que l'appelle à "fct" parte de quelque part. Ce quelque part est donc "this->*".