Vererbung und Static?



  • Hallo! Hab da ein Problem mit verbung und static.

    Ich habe eine Klasse B die als Basisklasse dient.
    Die Basisklasse B enthält variablen die Static sind.
    Nun habe ich weitere Klassen C und D die sich von B vererben.
    Ich möchte nun, dass ich für jeden Klassentyp C oder D eine eigene Static variable bekomme.
    Ich möchte nicht in C und D static variablen reinschreiben.
    Jemand eine Idee?



  • Eigene Static-Variablen bekommen ohne reinschreiben geht aber schwer...
    Von welchem Typ sind die Variablen? Welchen Namen willst du denen geben?
    Also soll B::staticVar ein anderer Type sein als C::staticVar? Willst du dir da vllt. grad ein Singleton basteln?

    Sei mal konkreter in deinen Ausführungen und gib uns vllt. etwas Code.



  • Da ist es vielleicht einfacher der Basisklasse einen statischen Container zu geben und einen Memberpointer der auf ein Element der Map zeigt und diesen im Konstruktor der jeweiligen Klasse auf das richtige statische Element umzubiegen und dann damit zu arbeiten statt direkt mit dem statischen Zeug zu hantieren.



  • @labrador

    class CB {
    public:
    	static int a;
    };
    
    int CB::a = 0;
    
    class CC : public CB {
    public:
    	CC() {
    	   //mach hier was mit a
    	}
    };
    
    class CD : public CB {
    public:
    	CD() {
    	   //mach hier was anderes a
    	}
    };
    

    In diesem code habe ich nur ein a, ich bräuchte aber 2 verschieden a.

    Ich möchte nun das die variable a für CC und CD verschieden ist. Da die Basisklasse CB allerdings sehr häufig verwendet wird, möchte ich nicht in jede klasse die sich von CB vererbt ein "static int a" schreiben. CC verebt von CB hat immer ein anderes a als CD vererbt von CB. Was ist ein Singleton?

    @Fellhuhn
    äh ja...hab ich leider nicht verstanden, ich les es nochmal und versuche es zu verstehen.



  • Warum nimmst du nicht statische Variablen in CC und CD und virtuelle Get/Set-Methoden in CB, die in CC und CD überschrieben werden und auf die jeweiligen statischen verweisen?

    class CB {
        static int a;
    
    public:
        virtual int &getA(){ return a; };
    };
    
    int CB::a = 0;
    
    class CC : public CB {
        static int a_CC;
    public:
        CC() {
           //mach hier was mit getA()
        }
        virtual int &getA(){ return a_CC; };
    };
    int CC::a_CC = 0;
    
    class CD : public CB {
        static int a_CD;
    public:
        CD() {
           //mach hier was anderes getA()
        }
        virtual int &getA(){ return a_CD; };
    };
    int CD::a_CD = 0;
    

    Ist zwar häßlich aber möglich.



  • Ok, ich mach es mal konkreter.
    Ich habe ein Klasse CSaveable. Vererbt man sich von dieser Klasse, so kann die abgeleitete Klasse ohne großen aufwand gespeichert/geladen werden. Natürlich muss man der CSaveable angeben was man denn speichern möchte. Ist jetzt hier nur grob skizziert.

    CSaveable {
    public:
       HRESULT addInfo(SString Description, const int& Information);
       HRESULT addInfo(SString Description, const float& Information);
       HRESULT addInfo(SString Description, ...);
    
       HRESULT Save(SString Filename);
       HRESULT Load(SString Filename);
    };
    
    //Jetzt eine Klasse die man speichern möchte.
    CIrgendwas : public CSaveable {
    private:
       int Info1;  //Variable die gespeichert werden soll
       int Info2;  //Variable die nicht gespeichert werden soll
    public:
       CIrgendwas() {
          addInfo("Tag", Info1);   //Der programmierer sagt im Constructor was er beim aufruf von Save() gespeichert/geladen haben will.
       }
    };
    
    void main {
       CIrgendwas irgendwas;
       irgendwas.Save("C:\\Klasseninformation.blup");   //Informationen aus der Klasse werden gespeichert
    }
    

    Wo kommt da jetzt das static ins spiel?
    Ich benötige das Static, damit ich für einen bestimmten Klassentyp die Adressen(genauer den Offset von der Information zu dem this-pointer) merken kann auf denen sich die Information zum speichern befindet. Das ganze würde ohne static ganz einfach sein, aber dann würde jede instanz der Klasse die Offsetinformation haben -> Speicherverschwendung.



  • Das wird so aber nciht klappen!
    In deinem Beispiel ist Info1 veränderlich. addInfo() wird nur einen Wert speichern können und bekommt so nicht mit ob sich der Wert geändert hat. Es wird also wohl immer nur der Wert gespeichert werden, der bei der Konstruktion des Objektes in Info1 gespeichert war! Also irgendwo völlig sinnlos!

    Und einen Offset zu speichern halte ich für einen schlchten Hack. Du willst ja dann wohl direkt auf den Speicher deiner Klasse zugreifen, halt ich für nicht gut...

    Warum nimmst du nicht einfach operator<<?
    Oder statt "addInfo" im Konstruktor aufzufufen als virtuelle Funktionen anzubieten, die abgeleitete Klassen implementieren müssen?



  • @labrador
    Der Wert Info1 ist veränderlich, deshalb wird ja auch eine (Offset)Adresse gespeichert und nicht der Wert selber.
    Wieso ist es denn ein "schlechter Hack" einen Offsetadresse zu speichern 😕?.

    Mag sein das sowas wie

    offset=(char*)this - (char*)Information;
    

    unschön aussieht, wenn es aber um Effizenz geht und andere das sowieso nicht zu Augen bekommen sollen, ist es meiner Meinung nach legitim.
    Für mich ist das sowas wie ein Pointer auf eine Adresse und das ist gang und gebe in C++.

    Warum nimmst du nicht einfach operator<<?
    Oder statt "addInfo" im Konstruktor aufzufufen als virtuelle Funktionen anzubieten, die abgeleitete Klassen implementieren müssen?

    Was meinst du mit operator<<? Ist das nicht letzendlich dasselbe was ich mache?

    Wie soll denn jemand der die Klasse CSavable nicht kennt, auf unkomplizierte art und weise die addInfo überschreiben?


  • Administrator

    JaykopX schrieb:

    ..., wenn es aber um Effizenz geht und ...

    Oh Gott ... (und ich bin nicht gläubisch)
    Wenn du da wirklich irgendetwas zusätzliches an Performance herausholst, dann ist es wohl im Bereich 0,000000000000000001%. Dafür hast du deinen Code verunstaltet und unwartbar gemacht. Ein sehr guter Einkauf ... 🙄

    Am besten überlegst du dir ein ganz anderes Design. Die Funktion addInfo hat gar nichts in CSavable verloren, sondern gehört eher in eine Archivklasse oder ähnliches. CSaveable sollte nur Load & Save haben, welche überschrieben werden und durch welche man eine Archivklasse bekommt, in welche man dann die einzelnen Member reinschreiben kann.

    Also irgendwas in der Art (grob):

    class Storer
    {
      // ..
    public:
      void put(int i);
      void put(float f);
      void put(char const* str);
      // usw.
    };
    
    class Loader
    {
      // ..
    public:
      int getNextInt();
      float getNextFloat();
      char const* getNextString();
      // usw.
    };
    
    class Saveable
    {
    public:
      virtual void load(Loader& loader) = 0;
      virtual void store(Storer& storer) = 0;
    };
    

    Wobei ich nicht mal dies, als wirklich gut empfinden würde, aber definitiv schon besser.

    Grüssli

    PS: Achte auf Performance erst am Ende, wenn du wirklich merkst, dass es Probleme gibt. Zuvor nur grobe Optimierungen, die erste Priorität liegt auf Wartbarkeit.



  • Ok, danke erstmal für eure Beiträge 👍 .
    Ich werde mal sehen was ich am besten mache und dann kurz bescheid geben.



  • JaykopX schrieb:

    Die Basisklasse B enthält variablen die Static sind.
    Nun habe ich weitere Klassen C und D die sich von B vererben.
    Ich möchte nun, dass ich für jeden Klassentyp C oder D eine eigene Static variable bekomme.

    Vielleicht mit ein wenig Template-Magie. Zumindest erwarte ich an dieser Stelle eine eigene static Variable für jede abgeleitete Klasse:

    template<typename T>
    class Base
    :   public T
    {
        protected:
            static int staticValue;
    };
    
    //...
    
    class Derived
    :   public Base<Derived>
    {
        //...
    };
    

    cu André



  • Die Basisklasse erbt hier von der Abgeleiteten Klasse und umgekehrt?

    Der Compiler macht das bei mir nicht mit, kannst du das in einem Code formulieren der sich compilen lässt? Ich steht da grad auf'm Schlauch. 😕


Anmelden zum Antworten