Vererbung statischer Funktionen - immer virtual oder nie?



  • Hi Leute,
    Sorry für 2 Threads, aber die Sachen haben nur bedingt was miteinander zu tun:

    class Base
    {
    static foo(){cout << "Base";}
    static Base* static_creator_function(){return new Base};
    };
    
    class Derived : public Base
    {
    static foo(){cout << "Derived";}
    static Base* static_creator_function(){return new Derived};
    
    };
    
    Factory->Register(0,Base::static_creator_function);
    Factory->Register(1,Derived::static_creator_function);
    
    Factory->Create(0)->foo();
    Factory->Create(1)->foo();
    

    Wird beides mal "Base" ausgegeben? Wenn ja, wie kann ich das umgehen?



  • Es wird beides mal "Base" ausgegeben, da beim Aufruf von foo() kein Virtual Dispatch stattfindet. Man kann das aber umgehen, indem foo() statt static virtual wird.



  • es gibt nen hack um zu umgehen,dass man die eigenschaften durch static verliert, das problem an der sache wäre nur, dass man bereits einen this pointer braucht, und wenn mand en hat, wozu dann noch static?



  • static und virtual widersprechen sich, logischerweise - ohne Instanz keine virtual function table, ohne virtual function table keine virtuelle Funktion. Es stellt sich für mich auch die Frage, wie man eine virtual static-Methode benutzen wollte...
    In diesem Fall löst sich das Problem so:

    class Base
    {
      virtual foo(){cout << "Base";}
      static Base* static_creator_function(){return new Base};
    };
    
    class Derived
    {
      virtual foo(){cout << "Derived";}
      static Base* static_creator_function(){return new Derived};
    };
    
    Factory->Register(0,Base::static_creator_function);
    Factory->Register(1,Derived::static_creator_function);
    
    Factory->Create(0)->foo();
    Factory->Create(1)->foo();
    

    Im Übrigen finde ich diese Art der factory ziemlich unschön (...und ich kann die Gelegenheit nutzen, in eigener Sache Werbung zu machen ;)) - ich hab da mal was geschrieben, was dich interessieren könnte: http://www.dev-geeks.org/forum/viewtopic.php?t=110



  • Ja, ich weiß, dass ich es über ne normale virtuelle Funktion machen kann, aber ich brauhc für diese Funktion eigentlich keine Instanz der Klasse. Link wird gleich mal angeschaut, darfst mir aber trotzdem sagen, was du an dieser Factory unschön findest 🙂



  • Auf die eine oder andere Art musste dich eh mit virtuellen Funktionen (oder direkt mit Funktionspointern, aber davon würde ich abraten) rumschlagen. Was ginge, wäre, von Hand eine statische vtbl anzulegen, also etwa so:

    struct vtbl_t {
      virtual void bar();
      virtual int baz();
    };
    
    struct foo {
      static vtbl_t vtbl;
    };
    
    //...
    
    void qux(vtbl_t &v) {
      v.bar();
    }
    
    //...
    
    qux(foo::vtbl);
    

    Sonderlich schöner Code ist das aber für meinen Geschmack nicht.



  • hui.
    Das ist mir ehrlichgesagt grad zu hoch 🙂



  • Das unschöne an der Factory ist, dass die Factory nicht in sich selbst gekapselt ist, sondern von Außerhalb Funktionen erwartet, die ihr die eigentliche Arbeit abnehmen. Die Factory ist dadurch leicht auszutricksen, z.B.

    Base *screw_factory() { return 0xbadc0ded; }
    
    Factory->Register(0, &screw_factory);
    

    Außerdem bin ich der Meinung, dass eine Factory ein Singleton sein sollte, damit man die Klasse nur ein mal registrieren muss, damit die Factory sie für immer kennt. (bzw. bis sie von Hand aus der Factory entfernt wird).



  • Ein Singleton ist sie seit Anfang an, war nur zu faul, das hier mit anzugeben 🙂
    Ich hatte es ursprünglich so gedacht, dass man nur die Klasse übergibt, bin dann aber gescheitert, weil ich nicht wusste, wie ich das am Besten mach. Bin grad am umbauen 😉


Log in to reply