Wie übergeben Sie einen Member-Funktionszeiger?

Lesezeit: 4 Minuten

Wie ubergeben Sie einen Member Funktionszeiger
Matt Pascoe

Ich versuche, eine Member-Funktion innerhalb einer Klasse an eine Funktion zu übergeben, die einen Member-Funktions-Klassenzeiger übernimmt. Das Problem, das ich habe, ist, dass ich nicht sicher bin, wie ich dies innerhalb der Klasse mit dem this-Zeiger richtig machen soll. Hat jemand Vorschläge?

Hier ist eine Kopie der Klasse, die die Member-Funktion übergibt:

class testMenu : public MenuScreen{
public:

bool draw;

MenuButton<testMenu> x;

testMenu():MenuScreen("testMenu"){
    x.SetButton(100,100,TEXT("buttonNormal.png"),TEXT("buttonHover.png"),TEXT("buttonPressed.png"),100,40,&this->test2);

    draw = false;
}

void test2(){
    draw = true;
}
};

Die Funktion x.SetButton(…) ist in einer anderen Klasse enthalten, wobei “object” ein Template ist.

void SetButton(int xPos, int yPos, LPCWSTR normalFilePath, LPCWSTR hoverFilePath, LPCWSTR pressedFilePath, int Width, int Height, void (object::*ButtonFunc)()) {

    BUTTON::SetButton(xPos, yPos, normalFilePath, hoverFilePath, pressedFilePath, Width, Height);

    this->ButtonFunc = &ButtonFunc;
}

Wenn jemand einen Rat hat, wie ich diese Funktion richtig senden kann, damit ich sie später verwenden kann.

Wie ubergeben Sie einen Member Funktionszeiger
Commodore Jäger

Um eine Elementfunktion per Zeiger aufzurufen, benötigen Sie zwei Dinge: Einen Zeiger auf das Objekt und einen Zeiger auf die Funktion. Du brauchst beides drin MenuButton::SetButton()

template <class object>
void MenuButton::SetButton(int xPos, int yPos, LPCWSTR normalFilePath,
        LPCWSTR hoverFilePath, LPCWSTR pressedFilePath,
        int Width, int Height, object *ButtonObj, void (object::*ButtonFunc)())
{
  BUTTON::SetButton(xPos, yPos, normalFilePath, hoverFilePath, pressedFilePath, Width, Height);

  this->ButtonObj = ButtonObj;
  this->ButtonFunc = ButtonFunc;
}

Dann können Sie die Funktion mit beiden Zeigern aufrufen:

((ButtonObj)->*(ButtonFunc))();

Vergessen Sie nicht, den Zeiger auf Ihr Objekt an zu übergeben MenuButton::SetButton():

testMenu::testMenu()
  :MenuScreen("testMenu")
{
  x.SetButton(100,100,TEXT("buttonNormal.png"), TEXT("buttonHover.png"),
        TEXT("buttonPressed.png"), 100, 40, this, test2);
  draw = false;
}

  • A pointer to the class – soll das sein A pointer to the object?

    – Vorac

    12. November 2014 um 15:06 Uhr

  • Vielen Dank. Konnte nicht herausfinden, dass die Syntax so etwas wie ((ButtonObj)->*(ButtonFunc))() ist

    – Nathanesau

    3. Juni 2016 um 16:22 Uhr

1646641812 988 Wie ubergeben Sie einen Member Funktionszeiger
Matt Cruikshank

Ich würde es dringend empfehlen boost::bind und boost::function für sowas.

Siehe Übergeben und Aufrufen einer Member-Funktion (boost::bind / boost::function?)

1646641815 440 Wie ubergeben Sie einen Member Funktionszeiger
Yuanlong Li

Ich weiß, das ist ein ziemlich altes Thema. Aber es gibt einen eleganten Weg, dies mit c++11 zu handhaben

#include <functional>

Deklarieren Sie Ihren Funktionszeiger so

typedef std::function<int(int,int) > Max;

Deklarieren Sie die Funktion, in die Sie dieses Ding übergeben

void SetHandler(Max Handler);

Angenommen, Sie übergeben ihm eine normale Funktion, dann können Sie es wie gewohnt verwenden

SetHandler(&some function);

Angenommen, Sie haben eine Member-Funktion

class test{
public:
  int GetMax(int a, int b);
...
}

In Ihrem Code können Sie es mit übergeben std::placeholders so was

test t;
Max Handler = std::bind(&test::GetMax,&t,std::placeholders::_1,std::placeholders::_2);
some object.SetHandler(Handler);

  • Danke dafür. Sie haben jedoch einen Typ: es ist std::placeholdersPlural.

    – Artfunkel

    26. Januar 2017 um 12:10 Uhr

Wären Sie nicht besser bedient, um Standard-OO zu verwenden. Definieren Sie einen Vertrag (virtuelle Klasse) und implementieren Sie diesen in Ihrer eigenen Klasse, übergeben Sie dann einfach eine Referenz an Ihre eigene Klasse und lassen Sie den Empfänger die Vertragsfunktion aufrufen.

Anhand Ihres Beispiels (ich habe die Methode ‚test2‘ in ‚buttonAction‘ umbenannt):

class ButtonContract
{
  public:
    virtual void buttonAction();
}


class testMenu : public MenuScreen, public virtual ButtonContract
{
  public:
    bool draw;
    MenuButton<testMenu> x;

    testMenu():MenuScreen("testMenu")
    {
      x.SetButton(100,100,TEXT("buttonNormal.png"), 
              TEXT("buttonHover.png"), 
              TEXT("buttonPressed.png"), 
              100, 40, &this);
      draw = false;
    }

    //Implementation of the ButtonContract method!
    void buttonAction()
    {
      draw = true;
    }
};

In der Empfängermethode speichern Sie den Verweis auf einen ButtonContract. Wenn Sie dann die Aktion der Schaltfläche ausführen möchten, rufen Sie einfach die ‘buttonAction’-Methode dieses gespeicherten ButtonContract-Objekts auf.

In dem seltenen Fall, dass Sie zufällig mit Borland C++Builder entwickeln und nichts dagegen haben, für diese Entwicklungsumgebung spezifischen Code zu schreiben (d. h. Code, der nicht mit anderen C++-Compilern funktioniert), können Sie das Schlüsselwort __closure verwenden . Ich habe einen … gefunden kleiner Artikel über C++Builder Closures. Sie sind hauptsächlich für die Verwendung mit Borland VCL vorgesehen.

  • Das ist eine ziemlich … obskure Lösung.

    – Josh Matthews

    25. September 2008 um 4:17 Uhr

  • Ja, es ist undurchsichtig. 🙂 Es gibt jedoch noch Delphi- und C++Builder-Legacy-Code im Firmenland. Am besten gründlich.

    – Parappa

    15. Oktober 2008 um 23:26 Uhr

Wie ubergeben Sie einen Member Funktionszeiger
Johannes Schaub – litb

Andere haben dir gesagt, wie man es richtig macht. Aber ich bin überrascht, dass Ihnen niemand gesagt hat, dass dieser Code tatsächlich gefährlich ist:

this->ButtonFunc = &ButtonFunc;

Da ButtonFunc ein Parameter ist, verlässt er den Geltungsbereich, wenn die Funktion zurückkehrt. Sie nehmen seine Adresse. Sie erhalten einen Wert vom Typ void (object::**ButtonFunc)() (Zeiger auf einen Zeiger auf eine Member-Funktion) und weist es diesem zu->ButtonFunc. Wenn Sie versuchen würden, this->ButtonFunc zu verwenden, würden Sie versuchen, auf den Speicher des (jetzt nicht mehr vorhandenen) lokalen Parameters zuzugreifen, und Ihr Programm würde wahrscheinlich abstürzen.

Ich stimme der Lösung von Commodore zu. Aber man muss seine Linie ändern

((ButtonObj)->*(ButtonFunc))();

da ButtonObj ein ist Zeiger widersprechen.

  • Das ist eine ziemlich … obskure Lösung.

    – Josh Matthews

    25. September 2008 um 4:17 Uhr

  • Ja, es ist undurchsichtig. 🙂 Es gibt jedoch noch Delphi- und C++Builder-Legacy-Code im Firmenland. Am besten gründlich.

    – Parappa

    15. Oktober 2008 um 23:26 Uhr

964400cookie-checkWie übergeben Sie einen Member-Funktionszeiger?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy