125 votes

Pointeur de fonction vers une fonction membre

J'aimerais configurer un pointeur de fonction comme membre d'une classe qui est un pointeur vers 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 à la compilation. Pourquoi ?

196voto

Johannes Schaub - litb Points 256113

La syntaxe est incorrecte. 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. Il est juste dit que l'on veut utiliser le pointeur stocké dans l'objet a . Préparez a une autre fois comme opérande gauche de la .* indique au compilateur sur quel objet appeler la fonction.

32voto

Bertrand Marron Points 9284

int (*x)() n'est pas un pointeur vers une fonction membre. Un pointeur vers une fonction membre s'écrit comme ceci : int (A::*x)(void) = &A::f; .

25voto

Heto Points 394

Appel d'une fonction membre sur une commande de type chaîne de caractères

#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 la classe void (A::*func)()

12voto

Jerry Coffin Points 237758

Vous devez utiliser un pointeur vers une fonction membre, et pas seulement un pointeur vers 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;
}

7voto

IllidanS4 Points 811

Bien que vous ne puissiez malheureusement pas convertir un pointeur de fonction membre existant en un pointeur de fonction ordinaire, vous pouvez créer un modèle de fonction d'adaptation d'une manière assez simple qui enveloppe un pointeur de fonction membre connu au moment de la compilation dans une fonction normale comme celle-ci :

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 qu'afin d'appeler la fonction membre, une instance de A doit être fournie.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X