2016-07-13 10 views
0

Ich begann letzte Nacht mit der Implementierung meines GUI-Systems für mein Spiel und entschied mich, Funktionszeiger zu verwenden, um GUI-Ereignisse zu behandeln. Ich habe sie vorher nicht verwendet, konnte aber eine grundlegende Implementierung implementieren. Ich möchte jedoch die Benutzerfreundlichkeit und das generische Verhalten des GUI-Systems erweitern. Zur Zeit habe ich einen Funktionszeiger in der GUI-Oberklasse unter dem geschützten Modifikator. Ich habe auch einen Getter (Callback) und einen Setter (subscribeEvent) in der Klasse, um der GUI ein Ereignis zuzuweisen. Es sieht zur Zeit ein wenig etwas wie folgt aus:C++: Wie man eine Funktion von einer beliebigen Klasse als Parameter übergibt

class GUI 
{ 
public: 
    ……. 
    …… 
    std::function<void()> callback() const { return eventCallback; } 
    void subscribeEvent(const std::function<void()>& callback) 
    { 
     eventCallback = callback; 
    } 

protected: 
    std::function<void()> eventCallback; 
}; 

Um eine Callback-Funktion, übergeben Sie in einer Leere Funktion subscribeEvent der gut arbeitet. Sie können jedoch keinen Modifikator für die Bereichsauflösung mit einer Funktion verwenden. Die übergebene Funktion muss also eine globale Funktion sein.

(MainGame.h): 

void global(); 

class MainGame 
{ 
public: 
    void Init(); 
    void nonGlobal(); 

private: 
    std::vector<GUI*> _guis; 
}; 

(MainGame.cpp): 

void MainGame::Init() 
{ 
    Button* button = new Button(……); //< Button is a subclass of GUI 
    button->subscribeEvent(global); //< This works fine 
    button->subscribeEvent(MainGame::nonGlobal); //< This does not work saying something like “void(MainGame) is not of type void()” 
    _guis.pushBack(button); 
} 

void MainGame::nonGlobal() 
{ 
…… 
} 

void global() 
{ 
…… 
} 

Wer weiß, wie die Parameter zu ändern, jeder Funktion im Rahmen einer Klasse zu ermöglichen, in weitergegeben werden. Dies wäre hilfreich, weil ich ein Tastenereignis von einem Spieler, Feind, Punkt kommen konnte, usw. Klasse und nicht jede Handler-Funktion global sein. Ich habe gesehen, dass High-Level-GUI-Systeme Ereignisse wie "event (handlerFunction, classtype)" übergeben, so dass Sie die Handler-Funktion und dann ein Objekt übergeben können, in dem sich die Handler-Funktion befindet. Dies ist ein Ansatz, den ich gerne machen würde.

+2

'button-> subscribeEvent ([this]() {nonGlobal();});' –

Antwort

1

Ihr Code würde funktionieren, wenn Sie die Funktion MainGame::nonGlobal statisch gemacht:

class MainGame 
{ 
public: 
    void Init(); 
    static void nonGlobal(); 

private: 
    std::vector<GUI*> _guis; 
}; 

Der Grund, warum Sie nicht eine nicht-statische Member-Funktion übergeben kann, ist, weil Member-Funktionen einen impliziten ersten Parameter (this) haben, in Ihr Fall vom Typ MainGame*. In der Tat hat die Funktion, die Sie gerade versuchen zu übergeben, die Signatur void(MainGame*) statt void(). Alternativ

, können Sie den this Parameter binden, indem eine Lambda anstelle der Funktion vorbei direkt:

button->subscribeEvent([this](){nonGlobal();}); 
0

ändern diese:

button->subscribeEvent(MainGame::nonGlobal); //< This does not work saying something like “void(MainGame) is not of type void()” 

zu

button->subscribeEvent(std::bind(&MainGame::nonGlobal, this)); 

Mit diesem ändern Sie haben ein anderes Problem der Lebensdauerverwaltung von this obwohl.

+0

Vielen Dank! Ich ging weiter und implementierte die std :: bind Funktionalität in die subscribeEvent Funktion, so dass ich MainGame :: nonGlobal ohne std :: bind im MainGame Code aufrufen konnte. Ich habe es auch generisch gemacht, damit ich Funktionen mit Argumenten einschließen kann: std :: function callback() const {return eventCallback; } \t template \t Leere subscribeEvent (T Beispiel F func, Args ... args) \t { \t \t Aufruf temp = {std :: bind (func , Beispiel, Argumente ...)}; \t \t eventCallback = temp; \t} – Connor

Verwandte Themen