Funktionzeiger in eine map



  • Ich komm im Moment nicht weiter. Mein Wissen ist anscheinend (noch) nicht gross genug. Ich versuche mein Problem zu beschreiben ohne meinen Lösungsansatz mit einzubeziehen.

    Problem:
    Ich möchte eine Basisklasse mit einer Funktion, welche einen Stream liest. Dieser Text Stream liefert den Namen einer Funktion aus der abgeleiteten Klasse. Diese Funktion ist also in der abgeleiteten Klasse implementiert. Nun soll die Basisklasse die Funktion der abgeleiteten Klasse ausführen. Die Anzahl der Funktionen kann für jede abgeleiteten Klasse verschieden sein. Einzig die Parameter und Rückgabewerte sind identisch.

    Wie kann ich das Problem am einfachsten lösen?



  • Nachdem Kompiliert wurde,bzw zur Laufzeit sind die Namen der Funktionen nirgends mehr vorhanden, sie sind dann wirrer Binärcode, soweit ich weiß kannst du zur Laufzeit nicht auf die "Namen" ,so wie sie im Code stehen, zugreifen.



  • Ich weiss. Darum wollte ich ja mit map den Funktionmsnamen der Funktion zuweisen.



  • Das geht einfach nicht. Zur Laufzeit sind die Funktionsnamen verschwunden. Das einzige, was du machen kannst ist, dass jede Klasse für sich selbst ihre Funktionsnamen als String inklusive Zeiger auf die Funktion verwaltet. Dann gibt es eine virtuelle Funktion in der Basisklasse, die aufgerufen wird, damit also in deiner abgeleiteten Klasse aufgerufen wird und dort kann sie dann entsprechend verteilt werden.
    Das wäre dann z.B. so

    class base {
    public:
       virtual some dispatch( std::string name, some s );
    };
    
    class derived : public base
    {
       typedef callback::callback_method<some (derived::*)(some)> callback_type;
       typedef std::map< std::string, callback_type > map_type;
    
       derived()
       {
           my_funcs_.insert( std::make_pair( std::string("some_func"), callback::make_callback_method( this, &derived::some_func ) ) );
       }
    
       some dispatch( std::string name, some s )
       {
           map_type::iterator it = my_funcs_.find(name);
           if( it != my_funcs_.end() ) return it->second.exec( some );
           else return some();
       }
    
       some some_func( some );
    
    private:
       map_type my_funcs_;
    };
    

    Also das kompiliert jetzt nicht, nur so als grundlegende Idee. Und natürlich den Memory Leak da... aber sollte ja klar sein^^



  • vieleicht kommt das deinen Vorstellungen näher.

    #include <map>
    #include <string>
    #include <iostream>
    using namespace std;
    
    class Base{ 
    public: 
    	typedef  void (Base::*TFunction)(); 
    
    	void callFunction(string functionName){
    		(this->*m_MapFunction[functionName])();
    	}
    
    	void regFunction(string functionName,  TFunction pFunction){
    		m_MapFunction[functionName]=pFunction;		
    	}; 
    
    	Base(){ 
    		regFunction("setValue", &Base::setValue); 
    		regFunction("getValue", &Base::getValue); 
    	};
    
    	void setValue(){
    		setValueVirtual();
    	}; 
    	void getValue(){
    		getValueVirtual();
    	};
    
    	virtual void setValueVirtual() = 0;
    	virtual void getValueVirtual() = 0;
    
    private: 
    	map<string, TFunction> m_MapFunction;
    };
    
    class Child : public Base
    {
    	void setValueVirtual(){
    		std::cout<<"Child::setValue\n";
    	}; 
    	void getValueVirtual(){
    		std::cout<<"Child::getValue\n";
    	};
    };
    
    int main()
    {
    	Child child;
    	child.callFunction("setValue");
    	child.callFunction("getValue");
    	return 0;
    }
    

    Gruß



  • Ja, stimmt, nimm lieber die Methode von Drehleiter 🙂 Dass du da in meinem Beispiel auch Methoden von allen anderen Klassen und statische Funktionen registrieren könntest ist für diesen Fall purer Overkill.

    Viele Grüße



  • Ok danke für die schnellen Antworten.
    Ich werde es mal versuchen.
    Grosses Kompliment: Super Forum!!! 👍



  • Ein Problem habe ich aber: Bei der vorgeschlagenen Lösung muss ich in der Basisklasse die Anzahl Funktionen schon wissen.
    Diese Anzahl sollte aber erst in der abgeleiteten Klasse definiert werden. Ich möchte die Basisklasse für mehrere abgeleiteten Klassen verwenden und die Anzahl Funktionen sollten demnach nicht fix sein.



  • Naja, mach das Pointer-zeugs in den abgeleiteten Klassen und schicke den Aufruf per virtueller Funktion dorthin. Sozusagen ein Mix aus unseren beiden Vorschlägen.



  • Jep. Meiner erster Test hat geklappt!
    Danke


Anmelden zum Antworten