Funktionspointer und ableiten :|



  • Die Idee: mit jeder weiteren abgeleiteten Klasse kommen neue Methoden hinzu, die über Funktionspointer dann allgemein aufgerufen werden. Das Problem hierbei ist aber, dass ich in der Basisklasse ja schon angebe auf welche Klasse sich die Methode bezieht. Vielleicht weiß jemand Rat, wie man das elegant lösen kann?

    Achja, ich verwende boost::function, wie man unschwer erkennen kann.

    class A {
    public:
        A()
        {
            registerCommand(0, &A::onNewConnection);
            registerCommand(1, &A::onAcceptConnection);
        }
        virtual ~A() {}
    
        void onReceive(int command, int interf)
        {
            methods[command](this, command, interf);
        }
    
    private:
        virtual void registerCommand(int id, void (A::*method)(int, int))
        {
            methods[id] = method;
        }
    
        virtual void onNewConnection(int command, int interf)
        {
            std::cout << "NEWCONNECTION\n";
        }
    
        virtual void onAcceptConnection(int command, int interf)
        {
            std::cout << "ACCEPT: interf: " << interf << std::endl;
        }
    
        typedef boost::function<void (A*, int command, int interf)> CommandMethod;
        std::map<int, CommandMethod> methods;
    };
    
    class B : public A {
    public:
        B() 
        {
    //        registerCommand(2, &B::onWhatever);  <-- das geht schief
        }
        virtual ~B() {}
    
    private:
        virtual void onAcceptConnection(int command, int interf)
        {
            std::cout << "ACCEPT: interf: " << (interf + 3) << std::endl;
        }
    
        virtual void onWhatever(int command, int interf)
        {
            std::cout << "whatever it takes";
        }
    };
    


  • Mach die Methoden protected und nicht virtuell.



  • Das ändert nichts, dass ich in Bs Konstruktor die registerCommand-Methode aufrufen kann. Außerdem geht mir ja dadurch der Vorteil verloren die Methoden zu überladen.



  • Ich meinte registerCommand, die anderen habe ich mir nicht näher angeschaut. Diese Methode sollte nicht virtuell sein und muss auf jeden Fall protected sein.



  • Er wird sich aber ewig beschweren, dass er B* nicht in A* konvertieren kann. Das Problem liegt ja scheinbar darin, dass sich die Methoden in der Map auf A beziehen und in Bs Konstruktor versucht wird eine Methode aus B dort reinzupacken.



  • Da hast du einen Designfehler. Wenn du einen A* Parameter hast, dann kannst du überhaupt nicht auf die neue Funktion zugreifen. Was spricht dagegen, "echte" Funktionen, von mir aus auch statische Member zu benutzen?

    class A {
    public:
        A()
        {
            registerCommand(0, &A::onNewConnection);
            registerCommand(1, &A::onAcceptConnection);
        }
        virtual ~A() {}
    
        void onReceive(int command, int interf)
        {
            methods[command](this, command, interf);
        }
    
    private:
        void registerCommand(int id, void (*fun) (int, int))
        {
            methods[id] = method;
        }
    
        static void onNewConnection(int command, int interf)
        {
            std::cout << "NEWCONNECTION\n";
        }
    
        static void onAcceptConnection(int command, int interf)
        {
            std::cout << "ACCEPT: interf: " << interf << std::endl;
        }
    
        typedef boost::function<void (int command, int interf)> CommandMethod;
        std::map<int, CommandMethod> methods;
    };
    
    class B : public A {
    public:
        B() 
        {
            registerCommand(1, &B::onAcceptConnection);
            registerCommand(2, &B::onWhatever);  <-- das geht schief
        }
        virtual ~B() {}
    
    private:
        static void onAcceptConnection(int command, int interf)
        {
            std::cout << "ACCEPT: interf: " << (interf + 3) << std::endl;
        }
    
        static void onWhatever(int command, int interf)
        {
            std::cout << "whatever it takes";
        }
    };
    

    So ists zwar nicht besonders elegant, aber es sollte funktionieren. Ich denk nochmal drüber nach 😉



  • Ja der geht der Glanz verloren 🙂

    Und irgendwie hab ich Probleme das jetzt zum Laufen zu bekommen.



  • So, natürlich gibt es einen guten Grund, warum die Methoden nicht statisch sein sollten. In ihnen soll dann nämlich noch auf Variablen des Objektes zugegriffen werden...


Log in to reply