Funktionenzeiger
-
Hallo!
warum funzt folgenes nicht?template<class T> class CommandBase { //Deklaration Function Pointer public: typedef void (T::*Base_FunctionPointer)(void); Base_FunctionPointer FktPtr; }; class CommandChild1 //: public CommandBase { public: void Kommando1(){cout<<"CommandChild1 - Kommando1"<<endl;}; }; int main (void) { CommandBase<CommandChild1> *pBase = new CommandChild1;Meldung:
'Initialisierung': 'CommandChild1 *' kann nicht in 'CommandBase<T> *' konvertiert werden
-
Du mußt Child von (einer passenden Spezialisierung von) Bas ableiten, damit das klappen kann:
class CommandChild : public CommandBase<CommandChild> { ... };
-
Danke CStoll.
Versuche gerade die Hinweise von Gestern im Detail zu verstehen!
-
Ist es nun möglich,
aus main() über FktPtr CommandChild1::Kommando1() aufzurufen?
-
Du kannst FktPtr einen Pointer auf diese Funktion nicht ablegen, weil Kommando1 nicht statisch ist.
Was willst du überhaupt damit machen? Man kommt manchmal nicht drumrum Funktionspointer zu verwenden, ansonsten würde ich jedoch dazu anraten Schnittstellen-Klassen mit virtuellen Funktionen stattdessen zu verwenden.
-
gib mal n Beispiel für Schnittst. klassen mit virt. Fkt.
-
Nimm doch das hier als Beispiel (Command wäre die Schnittstellenklasse, CmdFileOpen etc. bieten dann eine konkrete Implementierung an).
(PS: Das stammt aus deinem Thread von gestern ;))
-
class Interface { public: virtual int DoIt () { return 0; } }; class Child : public Interface { public: virtual int DoIt () { return 1; } }; int main () { Interface * pSomething = new Child (); int i = pSomething->DoIt (); }
-
Es gibt ne bessere Möglichkeit das ganze ohne virtuelle Funktionen im ConcreteCommand zu machen. Und ohne dass ein ConcreteCommand von einem AbstractCommand erbt. Das ganze funktioniert mit Templates.
Möchstest Du die Commands irgendwo verwalten, dann must du zunächst aber eine Stammklasse ohne Template erstellen.
Das ganze ist ungetestet.
struct BaseCommand { virtual void operator() = 0; };
Jetzt die Klasse die eine Funktion kapselt.
template <class T> struct AbstractCommand : public BaseCommand { typename void (T::*MyFunc)(); AbstractCommand(T* t, MyFunc func) : obj_(t), func_(func) {} void operator() { obj->*func(); } private: T* obj_; MyFunc* func };So kannst du auch übringens auch "normale" Funktionen kapseln. Wie, kannst du dir selbst überlegen.
Verwenden tust du das so:
// MyObject weiß nichts von einem AbstractCommand class MyObject { void foo() { std::cout << "MyObject::foo\n"; } }; int main() { AbstractCommand<MyObject> cmd(new MyObject, &MyObject::foo); cmd(); // <-- hier kommt der aufruf. }Wie gesagt, es ist ungetestet, sollte aber funktionieren.
Was mir noch einfällt: Man könnte eigentlich auch die BaseCommand als ein Template Parameter bestimmen lassen und somit festlegen ob operator() virtuell ist oder nicht:
// Reduziert auf das Nötigste... template <bool HasBaseCmd> struct ConstructCmd { struct AbstractCommand : public BaseCmd { ... }; }; template <> struct ConstructCmd<false> { struct AbstractCommand { ... }; };