webentwicklung-frage-antwort-db.com.de

Funktionszeiger auf Elementfunktion

Ich möchte einen Funktionszeiger als Mitglied einer Klasse einrichten, die auf eine andere Funktion in derselben Klasse verweist. Die Gründe, warum ich das tue, sind kompliziert.

In diesem Beispiel möchte ich, dass die Ausgabe "1" ist.

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())
}

Dies schlägt jedoch beim Kompilieren fehl. Warum?

75
Mike

Die Syntax ist falsch. Ein Elementzeiger ist eine andere Typkategorie als ein gewöhnlicher Zeiger. Der Mitgliedszeiger muss zusammen mit einem Objekt seiner Klasse verwendet werden:

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 Sagt noch nicht an welchem ​​Objekt die Funktion aufgerufen werden soll. Es heißt nur, dass Sie den im Objekt a gespeicherten Zeiger verwenden möchten. Wenn Sie dem Operator .* Ein anderes Mal a voranstellen, teilt dies dem Compiler mit, für welches Objekt die Funktion aufgerufen werden soll.

131

int (*x)() ist kein Zeiger auf die Mitgliedsfunktion. Ein Zeiger auf eine Mitgliedsfunktion wird folgendermaßen geschrieben: int (A::*x)(void) = &A::f;.

21
Bertrand Marron

Member-Funktion auf String-Befehl aufrufen

#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;
}

Achten Sie auf (this->*func)(); Und die Deklaration des Funktionszeigers mit dem Klassennamen void (A::*func)()

13
Heto

Sie müssen einen Zeiger auf eine Elementfunktion verwenden, nicht nur einen Zeiger auf eine Funktion.

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;
}
9
Jerry Coffin

Während dies auf den Sterling-Antworten an anderer Stelle auf dieser Seite basiert, hatte ich einen Anwendungsfall, der von ihnen nicht vollständig gelöst wurde. Für einen Vektor von Zeigern auf Funktionen gehen Sie wie folgt vor:

#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;
}

So etwas ist nützlich, wenn Sie einen Befehlsinterpreter mit indizierten Funktionen schreiben, die mit Parametersyntax und Hilfetipps usw. verwechselt werden müssen. Möglicherweise auch nützlich in Menüs.

3
Owl

Obwohl Sie einen vorhandenen Member-Funktionszeiger leider nicht in einen einfachen Funktionszeiger konvertieren können, können Sie auf einfache Weise eine Adapterfunktionsvorlage erstellen, die einen zur Kompilierungszeit bekannten Member-Funktionszeiger in eine normale Funktion wie die folgende einschließt:

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>;

Beachten Sie, dass zum Aufrufen der Member-Funktion eine Instanz von A angegeben werden muss.

0
IllidanS4