2017-08-10 4 views
0

Ich habe eine Klasse namens Menü. Hier ist die Header-Implementierung davon.Vorlage zum Ersetzen des Namensraums eines Rückrufs? cpp

Wie Sie sehen können, hat das Menü eine Liste von MenuItems. Ich denke nicht, dass die zusätzlichen Daten für dieses Problem relevant sind.

Hier ist die MenuItem Header-Datei:

class MenuItem{ 
public: 
    std::string  name; 
    int    (* callback)(std::string); 
    std::string  callback_param; 
    int    x_full; 
    int    y_full; 
    int    width_full; 
    int    height_full; 
    float   x; 
    float   y; 
    float   width; 
    float   height; 
    float   text_size; 
    float   text_margin_left; 
    float   text_margin_bottom; 
    bool   selected; 

      MenuItem(); 
    void create(std::string _name, int (*callback)(std::string) ); 
    void render(float _x, float _y, float _z); 
    void reshape(); 
    void set_size(int _w, int _h); 
    void set_height(int _h); 
    void set_param(std::string _p); 
    int  trigger(); 

}; 

Nun, da diese aus dem Weg ist, kann ich zu meinem eigentlichen Problem. Das Problem liegt innerhalb der Callback-Funktion in der MenuItem-Klasse. Der Rückruf erwartet etwas vom Typ

int (*callback(std::string a))

Das ist alles schön und funktioniert gut, wenn die Funktion ich es gebe Teil des Hauptcode ist oder eine statische innerhalb einer Klasse. Mein Ziel ist es jedoch, dieses Menü in anderen Klassen speichern zu können und sie einige ihrer eigenen Methoden zu übergeben. Dies ist ein Problem, da für die meisten meiner Klassen, die es nutzen möchten, sie in einen Rückruf vom Typ passieren

int (* BaseClass::callback(std::string a))

deshalb ich einen Compiler-Fehler erhalten, sagen, dass ich einen falschen Typ der am Übergang Menü als Rückrufobjekt.

Wie kann ich das umgehen? Eine Option, die ich untersucht habe, ist das Hinzufügen von Vorlagen zu den Menu- und MenuItem-Klassen. Ich möchte diese Option vermeiden, da ich bereits eine Menge Code geschrieben habe, zugegebenermaßen ein bisschen zu dumm (ohne voraus zu denken) und Refactoring würde viel Zeit verschwenden. Wäre das mit Vorlagen überhaupt möglich? Kann ich die Vorlage als Namespace und nicht als Objekttyp verwenden?

Welche anderen Optionen habe ich hier?

+0

Welche Version des C++ Standard passieren können verwenden Sie? Wenn Sie C++ 11 oder höher verwenden, können Sie eine Lambda-Funktion verwenden, um die entsprechende Elementfunktion eines in Lambda erfassten Objekts aufzurufen. – dlasalle

+0

Nö nicht mit C++ 11. Dies ist jedoch eine gute Option, ich werde es für die Zukunft im Auge behalten. – suli

+0

Öffentliche Daten meber ist fast nie eine gute Idee ... Und wahrscheinlich sollten 3/4 der Funktionen auch privat sein. Und wenn Sie einen Zeiger auf eine Mitgliedsfunktion wünschen, dann aktualisieren Sie Ihren Code ... ** Refactoring ist keine Zeitverschwendung. ** Wenn Sie schlechten Code behalten, werden Sie eventuell mehr Zeit verlieren, um ihn in der Zukunft zu beheben. – Phil1970

Antwort

1

könnten Sie std::function verwenden:

std::function<int(std::string)> callback; 

Benutzer noch Lambda/Functor als

menuItem.setCallback([this](std::string a) { return this->my_callback(a); } 
+0

Ich denke, die Lambda-Lösung ist cpp11 richtig? Aber ich mag die std :: function-Lösung. Im Grunde würde ich meine Menu- und MenuItem-Klasse ändern, um eine std :: -Funktion aufzunehmen, oder? und das wäre der Rückruf? – suli

+0

std :: function ist großartig, aber es funktioniert nicht in meinem Fall, da der Rückruf eine überladene Member-Funktion ist, so bekomme ich einen Kompilierfehler. Aber dank Ihrer Antwort lese ich die Lambda-Funktionen auf. Vielen Dank !das funktioniert – suli

+0

Lambda und Std :: Funktion sind in der Tat von C++ 11. – Jarod42

Verwandte Themen