Statische Variablen in Basisklasse und abgeleitete Klassen



  • Ich habe ein kleines Designtechnisches Problem, ich habe eine abstrakte Basisklasse, welche als Interface für abgeleitete Klassen dient, soweit so gut, jedoch benötigen alle abgeleitete Klassen zur Erzeugung ein paar statische Daten.

    Diese haben sie teilweise gemeinsam, daher wollte ich diese in die Basisklasse packen, initialisiert werden sie durch eine statische Methdoe setup() welche vor der Erzeugung eines Objekts der konkreten abgeleiteten Klassen geschieht.

    Allerdings teilen sich alle abgeleiteten Klassen ja die statischen Variablen ihrer gemeinsamen Basisklasse(n), nun ist es so, dass diese abgeleiteten Klassen gemeinsame Werte haben, diese jedoch mit unterschiedlichen Werten initialisieren, was ja nicht geht da sie die statischen Variablen teilen.

    Eine schlechte alternative wäre es die statischen Variablen in die abgeleiteten Klassen zu verlegen und für jede Klasse neu einzuführen, aber das beseitigt das Problem nur so lange wie man nicht eine neue Klasse von einer solchen abgeleiteten Klasse ableitet (um sie weiter zu spezialisieren).

    Was ich bräuchte wäre so etwas wie bei den templates, dort hat jede Instanz ihre eigenen statischen Variablen, aber die Schnittstelle bleibt gleich, nur würde man da nicht mehr die Polymorphie haben, da alle Klassen ihre eigene Basisklasse haben.

    Gibt es für solch einen Fall irgendeinen Trick um jeder Klasse ihre eigenen statischen Variablen zu garantieren, auch durch Vererbungshierachien durch?

    Ich hoffe es ist einigermaßen verständlich, hier mal nen kleines Beispiel:

    class Base
    {
    	public:
    	static void setup();
    
    	protected:
    	static int var1;
    	static int var2;
    };
    
    int Base::var1;
    int Base::var2;
    
    void Base::setup()
    {
    	//tut nix mit den statischen Werten
    }
    
    class Derived1 : public Base
    {
    	public:
    	static void setup();
    };
    
    void Derived1::setup()
    {
    	//Initialisiert die statischen Variablen mit den für Derived1 richtigen Werten
    	var1 = 12;
    	var2 = 13;
    }
    
    class Derived2 : public Base
    {
    	public:
    	static void setup();
    	protected:
    	static int var3;
    };
    
    int Derived2::var3;
    
    void Derived2::setup()
    {
    	//Initialisiert die statischen Variablen mit den für Derived2 richtigen Werten
        var1 = 25;
    	var2 = 37;
    	//neu hinzugefügte Variable, die nur Derived2 besitzt
    	var3 =45;
    }
    
    class Derived3 : public Derived2
    {
    	public:
    	static void setup();
    }
    
    void Derived3::setup()
    {
    	//Initialisiert die statischen Variablen mit den für Derived3 richtigen Werten
    	var1 = 57;
    	var2 = 21;
    	var3 = 37;
    }
    
    int main ()
    {
    	//Initialisiere die statischen Variablen von Derived1
    	Derived1::setup();
    	//Initialisiere die statischen Variablen von Derived2...oops die Werte von Derived1
    	//werden überschrieben
    	Derived2::setup();
    	//Und hier die von Derived3..wieder werden Werte überschrieben
    	Derived3::setup();
    }
    

    Für so etwas muss es doch ein Design Pattern oder sonst was geben um das zu lösen.



  • Wenn ich Dich richtig verstehe, willst Du pro Klasse (und nicht pro Instanz) unterschiedliche Werte derselben Variablen. Diese Werte werden einmal pro Klasse initialisiert und danach für diese Klasse nicht mehr verändert? Dann könnten normale Membervariablen ja reichen und Dein Konstruktor macht das setup. Verbrät natürlich ein bisschen Speicher und die Daten sind redundant.

    Eine Alternative wäre es pro Klasse diese Information in einem Container zu speichern, z.B. könnte die Basisklasse eine map<string, ClassInfo*> zur Verfügung stellen, die durch das setup gefüllt werden. Der string dient dann der Identifizierung der Klasse (also in Deinem Fall "derived1" usw.). Jede Klasse kann (muss aber nicht) einen neuen Kennzeichner haben. In setup prüfen, ob bereits der Eintrag in der Map bereits existiert. Das ganze könnte auch ausserhalb von einer Verwaltungsklasse gemacht werden.



  • niemand schrieb:

    Wenn ich Dich richtig verstehe, willst Du pro Klasse (und nicht pro Instanz) unterschiedliche Werte derselben Variablen. Diese Werte werden einmal pro Klasse initialisiert und danach für diese Klasse nicht mehr verändert? Dann könnten normale Membervariablen ja reichen und Dein Konstruktor macht das setup. Verbrät natürlich ein bisschen Speicher und die Daten sind redundant.

    Eine Alternative wäre es pro Klasse diese Information in einem Container zu speichern, z.B. könnte die Basisklasse eine map<string, ClassInfo*> zur Verfügung stellen, die durch das setup gefüllt werden. Der string dient dann der Identifizierung der Klasse (also in Deinem Fall "derived1" usw.). Jede Klasse kann (muss aber nicht) einen neuen Kennzeichner haben. In setup prüfen, ob bereits der Eintrag in der Map bereits existiert. Das ganze könnte auch ausserhalb von einer Verwaltungsklasse gemacht werden.

    Jedes Objekt damit zu belasten ist nicht so gut,
    aber die Idee mit der map gefällt mir 🙂
    Da die Objekte sowieso von ner factory Klasse erzeugt werden, sollte das ganz
    gut gehen, dann bekommt jedes Objekt nen Zeiger auf seine map, sind zwar 4byte
    Verschwendung, aber damit kann man leben.



  • Ein Problem habe ich nun doch noch, ursprünglich hätte ich der setup methode eine map<string,string> übergeben und die hätte die Daten entsprechend umgewandelt.
    Wenn ich einem Objekt nun eine map<string,string> übergebe müsste jeder Konstruktor diese Daten ja immer wieder aufs neue Parsen.

    Gibt es eine elegante Art die Daten fertig geparst zu übergeben?
    Wenn ich sie in der Factory Klasse umwandle, so muss ich beim hinzufügen von neuen Variablen auch immer die Factory Klasse mit ändern was ich nicht unbedingt will und dazu auch noch die Datenstruktur.
    Perfekt wäre daher einfach eine map die als key den namen der neuen Variable hat (ist bei der map<string,string> oben der fall) und dann als key den entsprechend geparsten Typ.



  • eine andere möglichkeit wäre, daß du die klassen nicht von base ableitest, sondern ein statisches objekt vom type base einfügst. die variablen und methoden von Base dürften dann natürlich nicht static sein. der nachteil ist aber, das du die Base-variablen und methoden dann immer mit Derived.Base.var1 bzw Derived.Base.setup() anstatt mit Derived.var1 bzw Derived.setup() aufrufen müßtest. außerdem wäre "Derived" dann nicht mehr von Base abgeleitet.



  • Konfusius schrieb:

    eine andere möglichkeit wäre, daß du die klassen nicht von base ableitest, sondern ein statisches objekt vom type base einfügst. die variablen und methoden von Base dürften dann natürlich nicht static sein. der nachteil ist aber, das du die Base-variablen und methoden dann immer mit Derived.Base.var1 bzw Derived.Base.setup() anstatt mit Derived.var1 bzw Derived.setup() aufrufen müßtest. außerdem wäre "Derived" dann nicht mehr von Base abgeleitet.

    Das wäre ja egal muss ich ja nur ein mal, aber diese Idee gefällt mir einfach nen struct für die Variablen und nen passendes setup und für alle Variablen die dazukommen leite ich davon einfach ab 🙂


Anmelden zum Antworten