Frage

Ich bin daran gewöhnt member-Funktionen nur als ein besonderer Fall der normalen Funktionen, wenn die Funktionen haben einen zusätzlichen parameter am Anfang Ihrer parameter-Liste für die "this" - Zeiger, das ist das Objekt, auf dem Sie die member-Funktion wirken soll.Ich haben verwendet boost::function diesem Weg in der Vergangenheit und nie auf Probleme gestoßen:

boost::function f<(void)(MyObject*, int, int)> = &MyObject::method_that_takes_two_ints;

Aber ich habe gesehen, diese syntax für member-Funktionszeiger:

void (MyObject::*f)( int, int ) = &MyObject::method_that_takes_two_ints;

In dieser syntax, der "this" - parameter ist nicht sichtbar.Das hat mich auch gewundert, wenn unter der Haube Zeiger-auf-member-Funktionen sind wirklich einer separaten Ungeheuer, und steigern Sie kümmerte sich um details für mich.

Was bedeutet der standard-diktieren Sie über die Platzierung von der "this" - parameter?Vielleicht auch nur an meinen compiler-extra 'dieses' argument kommt erste, und vielleicht auch auf andere Compiler, könnte es sein am Ende?Ich bin einfach glücklich, dass meine Art zu denken ist, im Einklang mit, wie mein Compiler (GCC4, VS2005) umgehen?Sind die Zeiger-auf-member-Funktionen immer nur ein spezieller Fall der Zeiger auf Funktionen mit einem extra parameter oder kann der compiler implementieren Sie anders?

War es hilfreich?

Lösung

Der standard sagt nichts darüber, wo die this Zeiger platziert werden soll, und in der Tat ist es ziemlich üblich, in eine andere Aufrufkonvention für member-Funktionen.(So der "this" - Zeiger nicht nur eine zusätzliche erste argument, es ist eigentlich an einem anderen Speicherort abgelegt, als der erste arg normalerweise der Fall ist)

Insbesondere, MSVC verwendet thiscall Aufruf-Konvention für die member-Funktionen, und stdcall anderswo.http://www.hackcraft.net/cpp/MSCallingConventions/#thiscall beschreibt die Unterschiede zwischen Ihnen, aber beachten Sie, dass thiscall speichert die this Zeiger in der ECX registrieren, während stdcall Filialen alle Parameter auf dem stack.

Sie sind auf jeden Fall besser behandeln als völlig unterschiedliche Typen.Ein Zeiger auf eine member-Funktion ist nicht nur ein Zeiger auf eine Funktion mit einem zusätzlichen parameter.

Andere Tipps

Der this Zeiger auf einem Zeiger auf ein Element nicht gespeichert ist (Mitglied Funktionszeiger sind ein Sonderfall dafür). Wenn Sie gerade tun

void (MyObject::*f)( int, int ) = &MyObject::method_that_takes_two_ints;

was dann gespeichert ist, ist nur die Informationen, die Member-Funktion auf einem objet aufgerufen werden soll, die Sie später zur Verfügung stellen müssen. Wenn Sie es nennen wollen, müssen Sie an ein Objekt übergeben, wo der Compiler die this Zeiger von bekommen.

MyObject o; (o.*f)(1, 2);

Ein Mitglied Funktionszeiger nur ein Elementzeiger, dessen Typ (das ist, zeigt auf) ein Funktionstyp. Der Standard besagt, dass die Mitgliedsfunktionszeiger nicht über ihre eigenen „Memberfunktion Typ“, dass sie zeigen, und dass würde irgendwie den dieser Zeigertyp.

int main() {
    typedef void fun() const;
    fun MyObject::*mem_function_ptr = 
        &MyObject::const_method_that_takes_two_ints;
}

fun in diesem Code ist der Funktionstyp. Der Typ, der eine „normale“ Funktion. Ein Zeiger-to-Funktion, wie ein Mitglied-Funktion-pointer Gegensatz ist nur ein Zeiger auf eine Funktion, die Art mit:

void foo() { cout << "hello"; }
int main() {
    typedef void fun();
    fun * f = &foo;
}

Während ein Zeiger-zu-Element-Funktion hat die zusätzliche Element-Zeiger-Ebene auf Oberseite dieser Funktionsart.

Etwas über den this Zeiger und wie sie auf das Objekt bezieht, die er zeigt (nicht technische, sondern nur die theoretischen Sachen):

Jedes Mitglied Funktion hat einen versteckten Parameter der implicit object parameter genannt, die MyObject& oder MyObject const& hat geben, je nachdem, ob Sie ein const oder nonconst Memberfunktion haben. Das Objekt, das Sie die Member-Funktion auf, o nennen, ist die implied object argument, der mit dem Parameter übergeben wird. In der Theorie der Norm, die die Regeln machen, die beschreiben, wie Member-Funktionen genannt werden, ist der implizite Objektparameter ein erster versteckten Parameter. Das ist konzeptionell und bedeutet nicht, dass es wirklich der Fall in Implementierungen. Die implizite Objekt Argument wird dann an diesem impliziten Objektparameter gebunden, möglicherweise impliziten Konvertierungen verursachen (wenn Sie also eine konstante Elementfunktion auf einem nicht-const-Objekt aufrufen, eine Qualifikation Konvertierung wandelt von MyObject zu MyObject const&. Das macht nicht konstante Funktionen eine bessere Wahl als const-Funktionen aufzurufen, für eine nicht-const-Objekt). Zum Beispiel kann man in diesem Code sagen:

struct A {
    operator int() const { return 0; }
};

int main() { 
    A a;
    int i = a; // implicit conversion using the conversion function
}

Dass das implizite Objekt Argument a vom Typ A die impliziten Objektparameter des Typ A const&, Objekt, das wird darauf dann durch den this Zeiger gebunden ist mit der Art A const* hier. Wichtig zu beachten ist, dass der implizite Objektparameter ist nur ein theoretisches Konstrukt, zu formalisieren, wie die Regeln für den Aufruf eine Elementfunktion bestehen (und Konstrukteure sie nicht enthalten), während die dieser Zeiger tatsächlich vorhanden ist. this ist ein Zeiger, denn wenn this eingeführt wurde, C ++ Referenzen noch nicht haben.

Ich hoffe, dass wird Ihnen helfen, die Sache zu verstehen.

Ein exzellenter Artikel auf Mitglied Funktionszeiger ist Codeproject Mitglied Funktionszeiger und die schnellstmögliche C ++ rel="nofollow Die Delegierten . Dieser Artikel beschreibt, Mitglied Funktionszeiger von den einfachen Fällen der ganzen Weg durch virtuelle Memberfunktionszeiger mit Mehrfachvererbung. Als Bonus bietet es eine Implementierung von Delegierten, die wirklich nützlich sein können.

Ja, Zeiger-to-Funktionen und Zeiger-to-Mitglieder sind völlig unterschiedliche Tiere. Zeiger auf Elemente benötigen ein Objekt gegeben Instanz, um die ->* oder .* Betreiber werden dereferenziert werden. Es gibt keine this Parameter verwendet, wenn ein Zeiger-auf-Mitglied macht, weil this bestimmt wird, wenn der Zeiger auf Element verwendet wird (das Objekt auf der linken Seite von ->* oder .*).

Beachten Sie die gibt es wahrscheinlich weniger einen Unterschied zwischen einer Zeiger auf Member-Funktion und einen Zeiger auf Membervariable als zwischen einer Zeiger-to-Member-Funktion und einem regelmäßigen Funktionszeiger ist.

Normalerweise Elementfunktionen und regelmäßige Funktionen können völlig unterschiedliche Aufrufkonventionen, so dass Sie nicht zwischen ihnen werfen können.

Beachten Sie, dass die Größe eines Zeigers zu Mitglied-Funktion unterschiedlich sein können verschiedene Compiler verwendet wird.

Eine andere Sache zu beachten, wie geschrieben in The Old New Thing Blog :

  

Die Größe eines   pointer-to-Mitglied-Funktion kann sich ändern,   je nach Klasse.

Sie sind auf jeden Fall verschiedene Arten und alle Annahmen, werden Sie machen Plattform / Compiler spezifisch.

Diese Seite hat mehr Informationen über die Implementierung der Mitgliedsfunktionspunkte als ich wollte schon immer wissen, einschließlich Implementierungsdetails für zahlreiche populäre Compiler.

Um alle Fragen zu beantworten: Ja, sie sind spezielle Zeiger, unterscheidet sich von gewöhnlichen Zeiger. Ja, boost :: Funktion sie erkennt.

Der Standard sagt nichts über die internen Details von Call-Stacks. In der Tat können viele Compiler integer rergisters verwenden, Gleitkommaregister und / oder der Stapel in Abhängigkeit von der tatsächlichen Argumentliste. A ‚this‘ Zeiger ist nur ein weiterer Sonderfall dar.

boost :: Funktion löst dieses Problem durch die Verwendung von zwei Codepfade intern. Sie können sehen, durch den Call-Stack für die beiden Fälle inspizieren. Wenn Ihr boost :: Funktion einen Zeiger auf Elementfunktion speichert, wird der Operator () spaltet die Argumentliste. Das erste Argument wird als das Objekt verwendet, auf das die Elementfunktion mit den übrigen Argumenten aufgerufen wird.

Für all andere Antwort zu ergänzen, arbeitet Boost.Function durch die Spezialisierung des Zuweisungsoperators auf Mitgliedsfunktionszeiger, es zu ermöglichen, zu erkennen, wenn Sie eine bestanden haben. Wenn Sie diese Funktion aufrufen, wird es intern neu zu interpretieren es auf die richtige Methode der Mitgliedsfunktionszeiger aufrufen ((obj->*fun)(args)).

Ich denke, man könnte diesen Link ganz interessant finden:

http://www.parashift.com/c++ -FAQ-lite / Zeiger-to-members.html

Es ist eine sehr gute Beschreibung von allem wollen Sie würden über Zeiger-to-Mitglieder kennen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top