2009-03-05 9 views
2

Dies scheint inkonsistent. Warum verwenden wir & Beispiel :: func anstelle von Beispiel :: func? Gibt es eine Verwendung für Beispiel :: func oder & exampleFunction? Es scheint nicht so, als könnten wir einen Verweis auf eine Funktion machen, so dass Beispiel :: func ausgeschlossen wird. und ich kann nicht an eine Möglichkeit denken, & exampleFunction zu verwenden, da exampleFunction bereits einen Zeiger zurückgibt.gibt es eine Verwendung für & func oder class :: func in C++?

#include <iostream> 
class Example { 
public: 
    void func() { std::cout <<"print me\n"; } 
}; 
void exampleFunction() { std::cout << "print me too\n"; } 
typedef void (Example::*ExampleFunc_t)(); 
typedef void (*ExampleFunction_t)(); 
int main() 
{ 
    Example e; 
    ExampleFunc_t  f = &Example::func; 
    ExampleFunction_t f2 = exampleFunction; 
    (e.*f)(); 
    f2(); 
    return 0; 
} 

Antwort

6

Weil der Standard Zeiger auf Funktionen definiert.

Sie müssen eigentlich immer den Adressoperator & verwenden, um einen Zeiger auf eine Funktion zu erhalten, aber für reguläre Funktionen und statische Elementfunktion ist eine implizite Konvertierung von Funktion zu Zeiger zu Funktion im Standard definiert.

Dies ist nicht für eine (nicht statische) Memberfunktion definiert, da Sie für eine nicht statische Memberfunktion keinen Lvalue erhalten können.

Aus dem C++ Standard:

4,3 Function-to-Zeiger Umwandlung

  1. ein L-Wert von Funktionstyp T mit einem R-Wert vom Typ „Zeiger auf T umgerechnet werden kann. "Das Ergebnis ist ein Zeiger auf die Funktion.

Fußnote 52:

Diese Umwandlung gilt nicht auf nicht-statische Elementfunktionen, weil ein L-Wert, der nicht erhalten werden kann, auf eine nicht statische Elementfunktion bezieht.

Ich denke, dass sie lieber nur & Funktion erlauben, aus Konsistenzgründen, sondern dass die implizite Konvertierung ist einfach ein Artefakt des C Erbe ...

+0

In C++ gibt es funktioniert auch Referenzen (typedef void (& FuncRef_t)()), aber keine Referenzen auf Mitgliedsfunktionen. – dalle

+0

Ja, ich denke, es ist nützlich, diese implizite Konvertierung für Funktionen zu haben. weil Sie meistens sowieso einen Zeiger übergeben möchten (Sie können keine Funktion "übergeben", also gibt es einen Zeiger auf sie durch implizite Konvertierung). Ich schätze, der Grund, warum T :: f nicht ausreicht, ist, dass es nicht eindeutig wäre: Wenn es bereits ein Elementfunktionszeiger –

+0

wäre, dann kann man nicht Base :: f(); eine Basisklassenfunktion aufrufen. du müsstest schreiben (this -> * Base :: f)(); was irgendwie scheiße ist. Also, die & T :: foo einen Zeiger zu bekommen ist eine gute Lösung, denke ich. –

1

Der Punkt verwendet Function Pointers. Für eine sehr grobe Beispiel an, dass Sie eine Klasse haben mit mehreren Mitgliedsvariablen, mit denen Sie benötigen die Elemente eines Arrays dieser Klasse zu sortieren, wie folgt aus:

struct CL { 
    int x, y, z; 
}; 

bool sort_by_x(const CL& obj1, const CL& obj2); 
bool sort_by_y(const CL& obj1, const CL& obj2); 
bool sort_by_z(const CL& obj1, const CL& obj2); 

... 

CL obj[100]; 
... 
sort(obj, obj+100, sort_by_x); 
... 
sort(obj, obj+100, sort_by_y); 
... 
sort(obj, obj+100, sort_by_z); 

Hier std :: sort verwendet wird um ein Array von CL-Objekten zu sortieren. Sehen Sie sich den dritten Parameter an, den Namen einer Funktion. Die Funktion std :: sort kann einen Funktionszeiger im dritten Parameter verwenden und diese Funktion als Komparator zum Sortieren des Arrays verwenden. Wie man sort_by_ * Funktionen definiert, hängt davon ab, dass std :: sort wie erwartet funktioniert.