2013-05-13 3 views
5

Ich weiß, das ist schon ein lang diskutiertes Thema, aber ich konnte noch keine Antwort finden, die mich befriedigt.C++ 11: Zeiger auf Member-Funktion mit std :: function :: target()

Frage kurz: Ist es nicht möglich, selbst Funktionsfunktionen von C++ 11 mit c: // function :: target() -Funktionen an c-style-Methoden zu übergeben?

Der folgende Code wird nicht funktionieren: der Aufruf an mbf.target() wird 0 zurückgeben und damit wird ein SEGFAULT erzeugt. Und ich verstehe nicht, warum, weil ich die Elementfunktion an ein generisches Funktionsobjekt binden, so sollte der Typ in Ordnung sein.

Was mache ich falsch oder versuche ich etwas Unmögliches zu tun?

#include <functional> 
using namespace std; 

typedef void (*CBType)(int, int); 
CBType myCB = 0; 

void regCallback(CBType cb) 
{ 
    myCB = cb; 
} 

class A 
{ 
public: 
    void memberCB(int a, int b) {} 

    void registerCallback() 
    { 
     auto mbMem = mem_fn(&A::memberCB); 
     function<void(int,int)> mbf = 
      bind(mbMem, *this, placeholders::_1, placeholders::_2); 
     regCallback(*mbf.target<void(*)(int,int)>()); 
    } 
}; 


int main() 
{ 
    A inst; 
    inst.registerCallback(); 
} 
+2

Es gibt einen Unterschied zwischen 'typedef void (* CBType) (int, int);' und 'typedef void (A :: * CBType) (int, int);'. Ich denke, dass du da oben versaust. Denken Sie daran, dass der Typ von '& A :: memberCB' 'void (A :: *) (int, int)' und nicht 'void (*) (int, int)' ist. Ihr Code wird nicht kompiliert. Können Sie einen Kompilierungscode angeben? – iammilind

+0

Richtig, ich habe die Header-Datei und den Namespace hinzugefügt. Dann kompiliert es mit g ++ und dem Compilerflag "-std = C++ 0x" – bobbel

+2

Unmöglich. Ziel ist das Abrufen eines Funktionszeigers, den Sie zuvor dort gespeichert haben. Es macht keine Magie und kann keine Goldfunktionszeiger aus Blei erzeugen. Sie können "Ziel" hier vergessen; es hat einen völlig anderen (und eher ungewöhnlichen) Anwendungsfall. –

Antwort

3

Ihre Member-Funktion ist nicht vom Typ void (*)(int, int) es von void (A::*)(int, int) Typ ist. Daher gibt targetnullptr zurück, da Sie versuchen, in den falschen Typ zu konvertieren. Ich würde empfehlen, CBType eine std::function<void(int, int)> zu machen.

+0

Das ist interessant. Also wird eine Deklaration "function mbf = ..." irgendwie immer noch einen internen Typ-Verweis auf die Klasse behalten und den Typ nicht zum Nicht-Mitglieder-Zeiger abstrahieren können? – bobbel

+0

Auch wenn es technisch möglich war, kann es nicht stimmen. Die Funktionalität der Klassenfunktion hängt von dem Objekt ab, an das sie gebunden ist, sie ist Teil ihres Kontexts. – SomeWittyUsername

+0

Ja, natürlich. Aber darum möchte ich das Objekt an die Funktion binden. Aber ich habe anscheinend eine zu hohe Sicht auf die Fähigkeiten von std. :: function. – bobbel

Verwandte Themen