2012-04-05 11 views
9

Ich versuche, ein Konzept und einen Fehler zu verstehen. Was ist daran falsch?Std :: Funktion mit nicht statischen Elementfunktionen

class A 
{ 
public: 
    A() 
    { 
     std::function<void(int)> testFunc(&A::func); 
    } 

private: 
    void func(int) {} 
} 

meine Frage, ist es möglich, jede Art von Objekt zu erstellen, die ein Mitglied einer bestimmten Instanz zu nennen ist in der Lage, wo std :: Funktion wie ein Mitglied Funktionszeiger wirkt, mit der Ausnahme, ohne die verrückte Typdefinition das kann Sie werden nicht als Funktionsparameter in erbenden Klassen verwendet. zum Beispiel:

class A 
{ 
public: 
    A() 
    { 
     index[WM_CREATE] = &A::close; 
     index[WM_DESTROY] = &A::destroy; 
    } 

protected: 
    map<UINT msg, void (A::*)(HWND, UINT , WPARAM, LPARAM)> index; 
    void close(HWND,UINT, WPARAM, LPARAM); 
    void destroy(HWND, UINT, WPARAM, LPARAM); 
}; 

class B : public A 
{ 
public: 
    B() 
    { 
     index[WM_CREATE] = &B::create; // error because it's not a pointer of type A::* 
    } 
private: 
    void create(HWND, UINT, WPARAM, LPARAM); 

}; 

Ich denke, ich auf dem richtigen Weg bin der Verwendung von std :: Funktionen wie folgt:

class A 
{ 
public:    //   Gigantic stl error with these two 
    A()    //       | 
    {    //       V 
     index[WM_CREATE] = std::function<void(HWND, UINT, WPARAM, LPARAM>(&A::close); 
     index[WM_DESTROY] = std::function<void(HWND, UINT, WPARAM, LPARAM>(&A::destroy); 
    } 

protected: 
    map<UINT msg, std::function<void(HWND, UINT, WPARAM, LPARAM)> > index; 
    void close(HWND,UINT, WPARAM, LPARAM); 
    void destroy(HWND, UINT, WPARAM, LPARAM); 
}; 

class B : public A 
{ 
public:     //    and this one 
    B()     //      | 
    {      //      V 
     index[WM_CREATE] = std::function<void(HWND, UINT, WPARAM, LPARAM)>(&B::create); 
    } 
private: 
    void create(HWND, UINT, WPARAM, LPARAM); 

}; 

wenn jemand was bedeuten diese riesigen kryptischen Fehler erklären könnte und wie man repariere sie, ich würde es sehr schätzen.

+0

Wenn Sie sagen "rufen Sie ein Mitglied einer bestimmten Instanz auf, in der sich' std :: function' wie ein Mitgliedsfunktionszeiger verhält ", bedeutet dies, dass die spezifische Instanz zum Zeitpunkt der Erstellung der' std :: -Funktion angegeben wird 'Objekt? Das schlägt die "void (int)" - Signatur vor, aber dann würde das Ergebnisobjekt nicht "wie ein Mitgliedsfunktionszeiger" funktionieren, es würde sich wie ein Callback/Funktor verhalten. Wenn Sie andererseits meinen, dass das resultierende 'std :: function'-Objekt sich tatsächlich wie ein Mitgliedsfunktionszeiger verhält, dann ist die Signatur falsch (z. B. könnte es stattdessen" void (A &, int) "sein). Welches ist es? –

+0

nicht sicher, was ein Callback/Funktor ist, aber es klingt irgendwie wie wir unterscheiden zwischen einer statischen Funktionen und eine nicht-statische Funktionen, und ich möchte es eine nicht-statische Funktion sein. Sie sind Handler, also müssen sie nur diese Instanzmitglieder manipulieren können. Wie in den Beispielen möchte ich, dass diese Funktion aufgerufen wird, wenn der entsprechende Map-Index übergeben wird. Ich möchte einfach folgendes tun: index [WM_CREATE] (hwnd, msg, lparam, wparam); und der einzige Weg, ich denke, dies zu tun, ist Speicherfunktion Zeiger oder etwas ähnliches dort.Ich kann nicht tun, tatsächlich Zeiger, weil es bricht die Vererbung :( – FatalCatharsis

+0

Kannst du nicht ['std :: mem_fun'] (http: //en.cppreference.com/w/cpp/utility/functional/mem_fn) stattdessen? –

Antwort

11

Ich denke, das Problem, das Sie haben, ist, dass eine Elementfunktion nicht nur einen Funktionszeiger erfordert, sondern einen Zeiger auf die aufrufendes Objekt. Mit anderen Worten, Elementfunktionen haben ein zusätzliches implizites Argument, das der Zeiger auf das aufrufende Objekt ist.

Um eine Member-Funktion in einer std :: Funktion eingestellt haben, müssen Sie std :: bind wie folgt verwenden:

std::function<void(int)> testFunc(std::bind(&A::func, this, _1)); 

Dies bindet die diesen Zeiger der aktuellen A-Instanz an die Funktion so hat es der Funktionszeiger und die Objektinstanz, die genug Informationen sind, um die Funktion ordnungsgemäß aufzurufen. Das Argument _1 gibt an, dass das erste explizite Argument beim Aufruf der Funktion bereitgestellt wird.

+0

Fehler C2065: '_1': nicht deklarierter Bezeichner. Ich nannte es wie 'HandlerIndex [WM_CREATE] = Std :: Funktion (Std :: Bind (& BasicWindow :: MsgCreate, this, _1))' – FatalCatharsis

+0

Sie benötigen einen Platzhalter für jedes Argument, so wäre es: 'std :: function (std :: bind (& BasicWindow :: MsgCreate, das, _1, _2, _3, _4))' –

+0

ah Gotcha, ich werde es versuchen, wenn ich zu Hause bin. – FatalCatharsis

0

meine Frage, ist es möglich, jede Art von Objekt zu erstellen, die

In diesem Fall die einzige Information, die in der Tat fehlt, ist, was bestimmte Instanz ein Mitglied einer bestimmten Instanz zu nennen ist in der Lage das Objekt std::function sollte verwenden: &A::func kann nicht allein verwendet werden (z. B. (this->*&A::func)(0) verwendet &A::func mit Instanz *this). Versuchen:

std::function<void(int)> testFunc = std::bind(&A::func, this); 

(Achten Sie darauf, dass std::bind(&A::func, *this) und std::bind(&A::func, this) etwas andere Semantik haben.)

Verwandte Themen