Nested class und Funktionspointer...
-
Hi,
Ich bin grad dabei mich mit Funktionspointern auseinander zu setzen. Als Hilfestellung für mein jetztiges Problem hab ich diesen Beitrag genommen. In abgewandelter Form ergibt sich damit folgende Ausgangssituation:
class Big { private: class Small { public: typedef int (Big::*BFunc)(); Small(BFunc pF, Big *Inst) { if ((pF == NULL)|| (Inst == NULL)) throw ... Small::pFct = pF; //funktioniert alles bestens Small::pBig = Inst; } int action() { //Variante 1 return *(Small::pBig).*(Small::pFct); //Compilerfehler: Big::Small::action must return a value //Variante 2 *(Small::pBig).*(Small::pFct); //Big::BigsFunc() wird nicht ausgeführt return 0; } private: Big *pBig = NULL; BFunc pFct = NULL; }; //Small public: Big() { Small S(&Big::BigsFunc, this); S.action(); } private: int BigsFunc(); }; //BigIch hab verschiedene Varianten ausprobiert, doch wie die Kommentare zeigen mit wenig Erfolg. Kann mir jemand weiterhelfen?
Thx, Maffe
-
#include <cassert> #include <iostream> class foo { private: class bar { public: typedef int (foo::*fnFoo)(void) const; bar(fnFoo, foo* ptrFoo) : m_fnFoo(fnFoo), m_ptrFoo(ptrFoo) { assert(ptrFoo != NULL); } int call_func() const { return (m_ptrFoo->*m_fnFoo)() }; private: foo* m_ptrFoo; fnFoo m_fnFoo; }; public: foo() { bar _inst(&foo::func, this); std::cout << _inst.call_func() << std::endl; } private: int func() const { return 5; } };... so sollte das korrekt aussehen.
-
Öhm gut. Darüber muss ich jetzt erstmal meditieren.

-
Naja ein Auruf sieht halt vom Prinzip so aus:
// fnFoo: Funktionszeiger: return_value (foo::*fnFoo)(param1, ...) /* const */; // * return_value ist im obigen Beispiel int. // obj: Objekt das genutzt werden soll um fnFoo aufzurufen. // param1, ... : Die Parameter in der Signatur die die Funktion aufweisen muss. (obj.*fnFoo)(param1, ...);. Da bei dir aber obj ein Pointer ist, kannst du entweder diesen Dereferenzieren:
(*ptrObj.*fnFoo)(param1, ...);oder den operator-> nutzen.
(ptrObj->*fnFoo)(param1, ...);Und Membervariablen kann man im Kontruktor initialisieren und nicht bei der deklaration/definition.
class foo { bar* m_ptr = NULL; };ist falsch:
class foo { bar* m_ptr; public: foo() : m_ptr(NULL) {} };ist korrekt.
Small::pFctehm wenn pFct static wäre, dann würde man das evtl. so machen. Ansonsten einfach pFct = . Im Kontruktor ist dem aber die Initialisierungsliste noch vorzuziehen.
-
Ok, also das mit dem Pointer hab ich gerafft.
Aber was ist jetzt mit der Initialisierungsliste? Macht man dieses typische Zuweisungsspielchen, also mit "=" nicht? Oder gibt's dort noch andere Vorteile, die ich jetzt grade übersehe?
Ich sollte vielleicht erwähnen, dass ich normaler Weise immer Definition von Implementation trenne.
-
Aber was ist jetzt mit der Initialisierungsliste?
Eine Liste, in der du angeben kannst, mit welchen Parametern der Konstruktor einer Membervariable aufgerufen werden soll. Oder mit welchem Wert eine Membervariable initialisiert werden soll ... um es vereinfacht auszudrücken.
class foo { public: foo(const bar& inst, bar* ptr_2) : inst(inst), ptr(ptr_2), ptr_1(NULL), primitiv(0) {} private: bar inst; bar* ptr; bar* ptr_1; int primitiv; };Macht man dieses typische Zuweisungsspielchen, also mit "=" nicht? Oder gibt's dort noch andere Vorteile, die ich jetzt grade übersehe?

Dadurch ersparst du dir den Aufruf eines Zuweisungsoperators. Wird direkt dem Kontruktor übergeben.
Ich sollte vielleicht erwähnen, dass ich normaler Weise immer Definition von Implementation trenne.
Man nimmt trotzdem eine Initialisierungsliste
Geht ohne Probleme:foo::foo(param1, ...) : m_param1(param1), ...(...) {}...
-
Gut gut. Aber der einzige Vorteil ist jetzt, dass ich mir den Zuweisungsoperator spare? Ja? Nein? Vielleicht?

-
Maffe001 schrieb:
Gut gut. Aber der einzige Vorteil ist jetzt, dass ich mir den Zuweisungsoperator spare? Ja? Nein? Vielleicht?

Nicht nur das, gewisse Dinge gehen nur mit einer initializer list:
class non_default_constructible { public: explicit non_default_constructible(int x) { } }; class foo { public: foo() : m_ndc(42), m_int_const(23) { } private: non_default_constructible m_ndc; int const m_int_const; };Versuch das mal ohne initializer-list
