J'aimerais configurer un pointeur de fonction en tant que membre d'une classe qui est un pointeur sur une autre fonction de la même classe. Les raisons pour lesquelles je fais cela sont compliquées.
Dans cet exemple, je voudrais que la sortie soit "1"
class A {
public:
int f();
int (*x)();
}
int A::f() {
return 1;
}
int main() {
A a;
a.x = a.f;
printf("%d\n",a.x())
}
Mais cela échoue lors de la compilation. Pourquoi?
La syntaxe est fausse. Un pointeur de membre est une catégorie de type différente d'un pointeur ordinaire. Le pointeur de membre devra être utilisé avec un objet de sa classe:
class A {
public:
int f();
int (A::*x)(); // <- declare by saying what class it is a pointer to
};
int A::f() {
return 1;
}
int main() {
A a;
a.x = &A::f; // use the :: syntax
printf("%d\n",(a.*(a.x))()); // use together with an object of its class
}
a.x
ne dit pas encore sur quel objet la fonction doit être appelée. Cela indique simplement que vous voulez utiliser le pointeur stocké dans l'objet a
. Préfixe a
une autre fois comme opérande de gauche du .*
, l'opérateur indiquera au compilateur sur quel objet appeler la fonction.
int (*x)()
n'est pas un pointeur sur une fonction membre. Un pointeur sur une fonction membre est écrit comme ceci: int (A::*x)(void) = &A::f;
.
Fonction de membre d'appel sur la commande string
#include <iostream>
#include <string>
class A
{
public:
void call();
private:
void printH();
void command(std::string a, std::string b, void (A::*func)());
};
void A::printH()
{
std::cout<< "H\n";
}
void A::call()
{
command("a","a", &A::printH);
}
void A::command(std::string a, std::string b, void (A::*func)())
{
if(a == b)
{
(this->*func)();
}
}
int main()
{
A a;
a.call();
return 0;
}
Faites attention à (this->*func)();
Et à la façon de déclarer le pointeur de fonction avec le nom de classe void (A::*func)()
Vous devez utiliser un pointeur sur une fonction membre, pas seulement un pointeur sur une fonction.
class A {
int f() { return 1; }
public:
int (A::*x)();
A() : x(&A::f) {}
};
int main() {
A a;
std::cout << (a.*a.x)();
return 0;
}
Bien que cela soit basé sur les réponses optimales ailleurs sur cette page, j’ai eu un cas d’utilisation qui n’a pas été complètement résolu; pour un vecteur de pointeurs vers des fonctions, procédez comme suit:
#include <iostream>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
class A{
public:
typedef vector<int> (A::*AFunc)(int I1,int I2);
vector<AFunc> FuncList;
inline int Subtract(int I1,int I2){return I1-I2;};
inline int Add(int I1,int I2){return I1+I2;};
...
void Populate();
void ExecuteAll();
};
void A::Populate(){
FuncList.Push_back(&A::Subtract);
FuncList.Push_back(&A::Add);
...
}
void A::ExecuteAll(){
int In1=1,In2=2,Out=0;
for(size_t FuncId=0;FuncId<FuncList.size();FuncId++){
Out=(this->*FuncList[FuncId])(In1,In2);
printf("Function %ld output %d\n",FuncId,Out);
}
}
int main(){
A Demo;
Demo.Populate();
Demo.ExecuteAll();
return 0;
}
Ceci est utile si vous écrivez un interpréteur de commande avec des fonctions indexées qui doivent être combinées avec la syntaxe des paramètres, des astuces, etc. Peut-être également utile dans les menus.
Bien que, malheureusement, vous ne puissiez pas convertir un pointeur de fonction membre existant en un pointeur de fonction simple, vous pouvez créer un modèle de fonction d'adaptateur de manière assez simple, qui englobe un pointeur de fonction de membre connu à la compilation dans une fonction normale, comme ceci:
template <class Type>
struct member_function;
template <class Type, class Ret, class... Args>
struct member_function<Ret(Type::*)(Args...)>
{
template <Ret(Type::*Func)(Args...)>
static Ret adapter(Type &obj, Args&&... args)
{
return (obj.*Func)(std::forward<Args>(args)...);
}
};
template <class Type, class Ret, class... Args>
struct member_function<Ret(Type::*)(Args...) const>
{
template <Ret(Type::*Func)(Args...) const>
static Ret adapter(const Type &obj, Args&&... args)
{
return (obj.*Func)(std::forward<Args>(args)...);
}
};
int (*func)(A&) = &member_function<decltype(&A::f)>::adapter<&A::f>;
Notez que pour appeler la fonction membre, une instance de A
doit être fournie.