2010-12-06 10 views
25

Wie erhalte ich eine Methode Zeiger auf eine bestimmte Überlastung eines Verfahrens:C++ überladene Methode Zeiger

struct A { 
    void f(); 
    void f(int); 
    void g(); 
}; 

Ich weiß, dass

&A::g 

ein Zeiger auf g ist. Aber wie bekomme ich einen Zeiger auf f oder f(int)?

Antwort

32
(void (A::*)()) &A::f 
(void (A::*)(int)) &A::f 

Funktionszeiger und Mitglied Funktionszeiger haben diese Funktion - die Überlastung durch zu lösen, was das Ergebnis zugewiesen oder gegossen wurde.

Wenn die Funktionen statisch sind, dann sollten Sie sie als normale Funktionen behandeln:

(void (*)()) &A::f; 
(void (*)(int)) &A::f; 

oder sogar

(void (*)()) A::f; 
(void (*)(int)) A::f; 
+0

Danke! Was ist, wenn die Elementfunktionen statisch sind? (Ich erhalte 'Fehler: Adresse der überladenen Funktion mit keiner kontextuellen Typeninformation') –

+0

@Neil: Sehen Sie meinen redigieren –

+0

Oh, ich sehe, ich werde gerade das erste' A :: 'für statische Funktionen los, da sie können zu regulären Zeigern umgewandelt werden. Sie schlagen mich dazu :) –

9

Sie haben nur das Ergebnis von &A::f, um zu werfen, die Mehrdeutigkeit zu entfernen :

static_cast<void (A::*)()>(&A::f); // pointer to parameterless f 
static_cast<void (A::*)(int)>(&A::f); // pointer to f which takes an int 
+0

Imho ist einer der besten Beiträge, die jemals in der SE über C++ veröffentlicht wurden ... – peterh

5

Danke an Stefan Pabst für die folgende Idee, wh Ich stellte es in einem fünfminütigen Blitzvortrag auf der ACCU 2015 vor. Ich erweiterte es mit Tag-Typen, um Überladungen mit ihrem cv-Qualifier und/oder Referenz-Qualifier zu lösen, und einer C++ 17-Variablenvorlage, um das zusätzliche Paar nicht eingeben zu müssen von Klammern, die sonst benötigt werden.

Diese Lösung funktioniert nach dem gleichen Prinzip wie die Antworten auf Cast-Basis. Sie vermeiden jedoch, dass Sie entweder den Rückgabetyp der Funktion oder im Falle von Memberfunktionen den Namen der Klasse, für die die Funktion steht, neu angeben müssen Mitglied von, da der Compiler in der Lage ist, diese Dinge abzuleiten.

bool free_func(int, int) { return 42; } 
char free_func(int, float) { return true; } 
struct foo { 
    void mem_func(int) {} 
    void mem_func(int) const {} 
    void mem_func(long double) const {} 
}; 

int main() { 
    auto f1 = underload<int, float>(free_func); 
    auto f2 = underload<long double>(&foo::mem_func); 
    auto f3 = underload<cv_none, int>(&foo::mem_func); 
    auto f4 = underload<cv_const, int>(&foo::mem_func); 
} 

Der Code der underload Vorlage Implementierung ist here.

Verwandte Themen