Ich möchte einen Funktionszeiger als Mitglied einer Klasse einrichten, die ein Zeiger auf eine andere Funktion in derselben Klasse ist. Die Gründe, warum ich das mache, sind kompliziert.
In diesem Beispiel möchte ich, dass die Ausgabe "1" ist.
class A {
public:
int f();
int (*x)();
}
int A::f() {
return 1;
}
int main() {
A a;
a.x = a.f;
printf("%d\n",a.x())
}
Dies schlägt jedoch beim Kompilieren fehl. Warum?
c++
oop
function-pointers
Mike
quelle
quelle
Antworten:
Die Syntax ist falsch. Ein Elementzeiger ist eine andere Typkategorie als ein gewöhnlicher Zeiger. Der Elementzeiger muss zusammen mit einem Objekt seiner Klasse verwendet werden:
a.x
sagt noch nicht, auf welchem Objekt die Funktion aufgerufen werden soll. Es heißt nur, dass Sie den im Objekt gespeicherten Zeiger verwenden möchtena
. Wenn Siea
dem.*
Operator eine andere Zeit als linken Operanden voranstellen, teilt dies dem Compiler mit, für welches Objekt die Funktion aufgerufen werden soll.quelle
(a.*a.x)()
Warum funktioniert(a.*x)()
nicht?a.x
ist ein Zeiger auf eine Mitgliedsfunktion der Klasse A.*a.x
Dereferenziert den Zeiger, sodass er jetzt eine Funktionsreferenz ist.a.(*a.x)
"bindet" die Funktion an eine Instanz (genau wiea.f
).(a.(*a.x))
ist erforderlich, um diese komplexe Syntax zu gruppieren, und(a.(*a.x))()
ruft die Methode tatsächlicha
ohne Argumente auf.int (*x)()
ist kein Zeiger auf die Mitgliedsfunktion. Ein Zeiger auf die Member-Funktion lautet wie folgt :int (A::*x)(void) = &A::f;
.quelle
Rufen Sie die Member-Funktion für den String-Befehl auf
Achten Sie auf
(this->*func)();
und wie Sie den Funktionszeiger mit dem Klassennamen deklarierenvoid (A::*func)()
quelle
Sie müssen einen Zeiger auf eine Elementfunktion verwenden, nicht nur einen Zeiger auf eine Funktion.
quelle
Während dies auf den Sterling-Antworten an anderer Stelle auf dieser Seite basiert, hatte ich einen Anwendungsfall, der von ihnen nicht vollständig gelöst wurde. Gehen Sie für einen Vektor von Zeigern auf Funktionen wie folgt vor:
So etwas ist nützlich, wenn Sie einen Befehlsinterpreter mit indizierten Funktionen schreiben, die mit Parametersyntax und Hilfetipps usw. verbunden werden müssen. Möglicherweise auch in Menüs nützlich.
quelle
typedef int (A::*AFunc)(int I1,int I2);
Obwohl Sie einen vorhandenen Elementfunktionszeiger leider nicht in einen einfachen Funktionszeiger konvertieren können, können Sie auf relativ einfache Weise eine Adapterfunktionsvorlage erstellen, die einen zur Kompilierungszeit bekannten Elementfunktionszeiger in eine normale Funktion wie diese umschließt:
Beachten Sie, dass zum Aufrufen der Member-Funktion eine Instanz von
A
bereitgestellt werden muss.quelle
Aufbauend auf der Antwort von @ IllidanS4 habe ich eine Vorlagenklasse erstellt, mit der praktisch jede Mitgliedsfunktion mit vordefinierten Argumenten und Klasseninstanzen als Referenz für einen späteren Aufruf übergeben werden kann.
Test / Beispiel:
Dies funktioniert natürlich nur, wenn die angegebenen Argumente und die Eigentümerklasse noch gültig sind. Soweit Lesbarkeit ... bitte vergib mir.
Bearbeiten: Unnötiges Malloc entfernt, indem das Tupel normal gespeichert wird. Geerbter Typ für die Referenz hinzugefügt. Option hinzugefügt, um stattdessen alle Argumente zur Aufrufzeit bereitzustellen. Jetzt arbeite ich daran, beides zu haben ...
Edit 2: Wie versprochen, beide. Die einzige Einschränkung (die ich sehe) besteht darin, dass die vordefinierten Argumente vor den zur Laufzeit angegebenen Argumenten in der Rückruffunktion stehen müssen. Vielen Dank an @Chipster für die Hilfe bei der Einhaltung der gcc. Dies funktioniert auf gcc unter Ubuntu und Visual Studio unter Windows.
quelle