Pointer auf Memberfunktion?
-
Hallo,
Ich habe zwei Klassen A und B und möchte einen Pointer auf eine Memberfunktion von A als Parameter an den Konstruktor der Klasse B übergeben. Wie geht das?
Ich meine das etwa so:class A { public: A(); ~A(); void function1(); } class B { public: B(void (*pt2Function)(void)); ~B(); } int main() { A myA; B myB(&A.function1); //nicht B myB(&A::function1); }
LG
-
Die Memberfunktionszeiger können nicht objektbezogen übergeben werden. Du kannst dir Memberfunktionen als normale Funktionen vorstellen, deren erster Parameter dem
this
-Zeiger entspricht.Also musst du zusätzlich zur Funktion das Objekt übergeben, auf der du sie aufrufst. Zur Syntax findest du hier nützliche Informationen.
-
huhu,
so z.B.:
#include <iostream> using namespace std; class A { public: void function1() { cout << "Hallo Welt"; } }; class B { public: B(void (A::*ptmf)() ) { A a; (a.*ptmf)(); }; }; int main() { A a; void (A::*ptmf)() = &A::function1; B b(ptmf); system("pause>nul"); return 0; }
-
Objekt muss übergeben werden, wie der Vorredner schon gesagt hat. Kannst es dann auch dynamisch mit Templates machen:
#include <iostream> class A { public: void foo() const { std::cout << "foo A" << std::endl; } }; template <class T> class B { private: typedef void (T::*A_func)() const; public: B(const T &a, A_func foo) { (a.*foo)(); } }; int main() { A a; B<A> b(a, &A::foo); std::cin.get(); }
-
@Dweb: Deine Variante kann ich nicht verwenden da die Klasse A in meinem Fall den exclusiven Zugriff auf eine Ressource hat und ich daher kein 2tes Objekt vom Typ A erzeugen darf.
@Marvin0r:
Danke, deine Variante sieht gut aus, aber könntest du mir vielleicht erklären was da passiert?LG
-
B<A> b(a, &A::foo);
Einfach gesagt:
1. B<A> bedeutet, dass das "T" in der Klasse B durch den Datentyp "A" ersetzt wird.
--> Überall wo "T" in der Klasse B steht, denkst du dir also ein "A".2. Dann übergibst du dem Konstruktor das Objekt "a" und die Adresse der Funktion "foo",
und dann kannst du die Funktion "foo" über das Objekt "a" aurufen.
-
C++ Lernender schrieb:
@Dweb: Deine Variante kann ich nicht verwenden da die Klasse A in meinem Fall den exclusiven Zugriff auf eine Ressource hat und ich daher kein 2tes Objekt vom Typ A erzeugen darf.
@Marvin0r:
Danke, deine Variante sieht gut aus, aber könntest du mir vielleicht erklären was da passiert?LG
Tschuldigung, hab deinen Benutzernamen net gelesen. Vielleicht sind Templates dann doch etwas zu "hoch" für die Aufgabe bzw. ohne lässt es sich leichter verstehen. Leicht abgewandelt und ohne Templates sieht es dann so aus (diesmal sogar mit Erklärungen :D):
#include <iostream> class A { public: void foo() const { std::cout << "foo A" << std::endl; } }; class B { private: typedef void (A::*A_func)() const; // Ein Typedef definiert einen Alias für einen Typ, // hier wäre es ein Typedef für einen Methodenpointer, // der eine Funktion in der Form "void funktion() const" erwartet. // const kannst du evtl. auch weglassen (google mal nach const correctness, // die sollte man sich so früh wie möglich angewöhnen) public: // Im Konstruktor von B übergibst du dann eine konstante Referenz auf ein // A-Objekt (es ginge auch ein Pointer) und eine Funktion (hier zeigt sich // der Vorteil des obigen typedefs: statt "B(const A &a, void (A::*foo)() const" kannst du einfach "B(const A &a, A_func foo)" schreiben. // Probier beide Schreibweisen zum besseren Verständnis mal aus) B(const A &a, A_func foo) { (a.*foo)(); // Hier rufst du die Methode, auf die der Methodenpointer zeigt, mit // dem Objekt a auf (.* dereferenziert und greift gleichzeitig auf ein Member zu) } }; int main() { A a; B b(a, &A::foo); std::cin.get(); }
Hoffentlich wird es dadurch klarer...
-
WOW DANKE,
wenn ich aber jetzt versuche die Funktion aus A innerhalb einer Funktion von B aufzurufen erhalte ich einen Linker-Error (Nicht auflösbares externes 'B::B()' referenziert von ...).
also so:#include <iostream> class A { public: void foo() const { std::cout << "foo A" << std::endl; } }; class B { private: typedef void (A::*A_func)() const; public: B(); test(const A &a, A_func foo) { (a.*foo)(); } }; int main() { A a; B b; b.test(a, &A::foo); std::cin.get(); }
Warum kommt dieser Fehler und wie kann ich das richtig schreiben??
Und die nächste Frage ist: kann ich innerhalb der Klasse B eine Variable erzeugen die den Zeiger auf die Memberfunktion von A hält um nicht die Referenz von A und den Pointer auf die Memberfunktion zu speichern?? In etwa so:
class B { private: typedef void (A::*A_func)() const; int (*function)(void); public: B(const A &a, A_func foo) { function = a.*foo; } test() { function(); } };
-
Ups, da hab ich was übersehen. Das B(); gehört natürlich weg, dann funktioniert es einwandfrei.
Und einen Rückgabewert sollte die Funktion test() natürlich auch haben.
Bleibt nur noch die 2te Frage.LG
-
Nein. Du musst Instanz und Funktion einzeln speichern.
Z.B. so:
class B { private: typedef void (A::*A_func)() const; A_func function; A *instanz; public: B(const A &a, A_func foo) { instanz = &a; function = foo; } void test() { ((*instanz).*function)(); } };