Dynamisch erstellen Sie eine Funktion Zeiger, ruft eine Methode auf einer bestimmten Instanz
Ich vermute, dass dies unmöglich ist, aber dachte, ich würde bitten. Sagen wir ich habe eine Klasse mit einer Methode:
class A {
public:
void b(int c);
};
Kann ich einen Zeiger auf member-Funktion:
void (A::*ptr)(int) = &A::b;
(someAInstance.*ptr)(123);
Kann ich auch Missbrauch Funktionszeiger und einen Zeiger, der die A
argument direkt (ich weiß nicht, ob dies sicher ist, aber es funktioniert auf meiner Maschine):
void (*ptr2)(A*, int) = (void (*)(A*, int))&A::b;
(*ptr2)(&someAInstance, 123);
Was ich wollen ist irgendwie curry die A
argument, und erstellen Sie eine Funktion Zeiger, dauert nur ein int
, fordert aber die A::b
Methode auf einen bestimmten A
Beispiel habe ich vordefiniert. Die A
Instanz bleiben konstant für die jeweilige Funktion Zeiger, aber möglicherweise gibt es mehrere Funktionszeiger alle auf das gleiche A::b
Methode, aber mit unterschiedlichen A
Instanzen. Ich könnte zum Beispiel eine eigene wrapper-Funktion:
A* someConstantA = new A;
void wrapper(int c) {
someConstantA->b(c);
}
void (*ptr3)(int) = &wrapper;
Jetzt kann ich mit ptr3
ohne zu wissen, welche besonderen A
es ist die Versendung der Aufruf, aber ich hatte zu definieren, die eine spezielle Funktion zu behandeln. Ich brauche einen Weg, um Hinweise für eine beliebige Anzahl von A
Instanzen, so kann ich nicht hartcodieren so. Ist dies in irgendeiner Weise möglich?
Bearbeiten: Sollte erwähnt haben, ich bin gefangen in C++03 land ist, und auch nicht die Verwendung von Boost
- Es muss eine Funktion Zeiger? Was Sie tun möchten erfolgt oft über die Funktion von Gegenständen (z.B. mit
std::bind
). - Alles callable funktioniert; ich weiß nicht
std::bind
, jetzt zu Lesen - ^^^ oder
boost::bind
wenn Sie nicht über C++11. - Ein function-Objekt ist ein Objekt, das definiert
operator()
so können Sie es verwenden, wie eine Funktion. Intern kann es halten einethis
Zeiger und Funktionszeiger.std::bind
ist ein Weg, es zu tun, oder Sie können von hand die Rollen. - Ah, ich habe gerade festgestellt
std::bind
ist in c++11 auch, also ich kann es nicht verwenden (bearbeitet die Umwelt, ich bin stecken mit in der Frage). Ich glaube nicht, machen Sie eine Klasse, dieoperator()
; das könnte der Weg, dies zu tun - (template -) Klasse, die operator() ist ein wirklich einfacher Weg zu gehen, IMO. Die etwas weniger leserlich Weg wäre, um typedef void (ptr2)(A, int) und ein makro verwenden.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wenn du eine ausreichend neue compiler (z.B. gcc 4.2+), es sollte TR1, wo könnten Sie
std::tr1::bind
:Es ist auch machbar in reinen C++ - 03 ohne TR1, aber auch viel mehr messier:
Könnten Sie auch schreiben Sie Ihre eigene function-Objekten.
Beachten Sie, dass in allen oben genannten Fällen müssen Sie sehr vorsichtig sein, über die Lebensdauer der
a
da, die bloßen Zeiger. Mitstd::tr1::bind
, konnte man sich wenigstens wickeln Sie den Zeiger in einestd::tr1::shared_ptr
aus, so dass er nur Leben, solange die function-Objekt.Nicht erstellen Sie eine wrapper - Funktion, erstellen Sie eine wrapper -Funktor. Dies ermöglicht Ihnen zu Kapseln, wie immer Sie wollen (z.B. eine
A*
) in ein callable-Objekt.Wenn Sie mit C++11, können Sie einen lambda-Ausdruck (code ungetestet):
Ich würde mit Boost::bind für diese.
Grundsätzlich:
Ich denke, dass sollte funktionieren. Ich bin auch mit auto hier, Rückschlüsse auf die Art zurückgegeben, die von boost::bind() zur compile-Zeit, die Ihre compiler möglicherweise nicht unterstützen. Sehen Sie diese andere Frage bei stackoverflow für eine Erläuterung der return-Typ binden.
Boost unterstützt Sie zurück zu Visual Studio 2003 (glaube ich) und diese alle das wird da arbeiten, obwohl Sie verwendet werden, BOOST_AUTO, denke ich. Siehe die andere Frage, die bereits in Verbindung, um eine Erklärung.
Was Sie wollen, ist nicht möglich.
Um zu sehen, warum, davon ausgegangen, dass es möglich ist - die Funktion Zeiger muss auf eine Funktion irgendwo in der ausführbaren Datei oder einer Ihrer Bibliotheken, also es muss sich auf eine Funktion, die weiß, welche Instanz von
A
zu nennen, ähnlich wie Ihre wrapper-Funktion. Weil die Instanz vonA
erst zur Laufzeit bekannt ist, müssten Sie erstellen, die diese Funktionen zur Laufzeit, das ist nicht möglich.Was Sie zu tun versuchen ist möglich in C++03, solange Sie glücklich sind, zu übergeben, um ein function-Objekt und nicht als eine Funktion Zeiger.
Als andere haben bereits Lösungen geboten, die mit C++11 lambdas, TR1 und boost (alle sind hübscher als die unten), aber Sie erwähnt Sie nicht verwenden können, C++11, ich werde beitragen, eine in reinen C++ - 03:
Ich gearbeitet habe, etwas mit einer Vorlage Delegate-Klasse.