Klassenstruktur durch Vererbung erweitern



  • Hallo zusammen,

    ich hoffe jemand kann mir bei folgenden Problem helfen:
    Ich habe drei Klassen, nennen wir sie mal A,B und C, die sozusagen gegeben sind, d.h. diese sollten nicht geändert werden. Sie stehen in folgender Beziehung zueinander: A hat u.A. eine Membervariable vom Typ std::vector<B>, und B eine Membervariable vom Typ std::vector<C>, wobei die Membervariablen private sind und durch (sowas wie) Getter aufgerufen werden.
    In Klasse B und C sind Funktionen, die ein Objekt vom Typ B bzw. C in sich selbst kopieren. In Klasse A ist desweiteren eine (recht komplizierte) Funktion, die Daten aus einer Datei/Datenbank ausliest, und damit die Struktur füllt.
    Zum Beispiel ergibt sich dann sowas:

    class C {
    private:
    	int fooC;
    public:
    	int Get_fooC() {return fooC;};
    	void CopyData(C tmpC) {
    		/* Kopiert alles aus tmpC in sich selbst */
    	}
    }
    
    class B {
    private:
    	vector<C> Cs;
    	int fooB;
    public:
    	void GetC(int index, C &tmpC) {tmpC = Cs.at(index);};
    	int Get_fooB() {return fooB;}
    	void CopyData(B tmpB) {
    		/* Kopiert alles aus tmpB in sich selbst */
    	}
    }
    
    class A {
    private:
    	vector<B> Bs;
    	int fooA;
    public:
    	B GetB(int index) {return Bs.at(index);};
    	int Get_fooA() {return fooA;}
    	void LeseDatei(string filename) {
    		/* Komplizierte Funktion um die Bs mit Daten aus filename zu füllen */
    	};
    }
    

    Vielleicht habe ich jetzt irgendwo nen Syntax-Fehler beim tippen fabriziert, jedenfalls funktioniert das soweit alles wie es soll. Jetzt also zum eigentlich Problem:

    In den Klassen B und C benötige ich eine weitere Variable, z.B. muhB und muhC. Ich könnte dann sowas machen wie

    class myC : public C {
    private:
    	int muhC;
    public:
    	int Get_muhC() {return muhC;};
    }
    
    class myB : public B {
    private:
    	int muhB;
    public:
    	int Get_muhB() {return muhB;};
    }
    

    Um diese Klassen zu verwenden, müsste ich mit meinem begrenzten die Struktur von oben Quasi neu erstellen, also eine Klasse myA erstellen, die vector<myB> enthält, in myB müsste dann aber z.B. noch sowas wie vector<myC> hinein. Das finde ich aber 1. nicht sehr elegant und 2. gibt das auch Probleme, da ich z.B. A::LeseDatei nicht mehr ohne weiteres verwenden kann.

    Meine Frage also: Geht das auch irgendwie eleganter zu lösen? Wenn nein, könnte ich vielleicht ein paar allgemeine Tipps zu dem Problem bekommen?

    Nochmal zu den Spielregeln: An A,B,C darf nicht herumgeschraubt werden, für myB, myC und ggf. myA gibt es keine Einschränkungen.
    Ich finde die Sache recht kompliziert, deshalb hoffe ich, mich halbwegs verständlich ausgedrückt zu haben. Falls nicht, bitte fragt einfach nach.

    Viele Grüße, Nowi



  • Um diese Klassen zu verwenden, müsste ich mit meinem begrenzten die Struktur von oben Quasi neu erstellen, also eine Klasse myA erstellen, die vector<myB> enthält, in myB müsste dann aber z.B. noch sowas wie vector<myC> hinein. Das finde ich aber 1. nicht sehr elegant und 2. gibt das auch Probleme, da ich z.B. A::LeseDatei nicht mehr ohne weiteres verwenden kann.

    Warum musst du das alles neu erstellen? - Wenn du ein Objekt von myC erstellst, dann kannst du da die Funktionen von C ganz normal aufrufen und benutzen. Du erweiterst dann einfach noch um muhC und machst, was auch immer du machen willst.

    Oder meinst du eher, dass du muhC nicht mit der Funktion der Basisklasse speichern und laden kannst? - Das wird in der Tat ohne Unterstützung von C recht schwer ausser es werden für einen solchen Fall Funktionen angeboten, was ich aber irgendwie bezweifle.
    Je nachdem, woher denn der Wert kommt kannst du den ja aber auch einfach nach dem laden wieder neu berechnen (dafür die Methode einfach überschreiben deine spezifischen Sachen machen und dann die Basisklassenmethode aufrufen).

    Und jetzt noch zu etwas anderem, was mir aufgefallen ist:

    void CopyData(B tmpB) {
            /* Kopiert alles aus tmpB in sich selbst */
        }
    

    Diese Funktion klingt für mich sehr nach dem Zuweisungsoperator '='. Was mich aber eher skeptisch macht ist das Funktionsargument. Da ertellst du ja bereits eine B-Kopie und du müsstest eigentlich nur noch die Werte von tmpB und dem aktuellen Objekt tauschen (Copy-and-swap Idiom).

    Ps:
    Und ja, Syntaxfehler hast du da ein paar drin. 😉



  • drakon schrieb:

    Warum musst du das alles neu erstellen? - Wenn du ein Objekt von myC erstellst, dann kannst du da die Funktionen von C ganz normal aufrufen und benutzen. Du erweiterst dann einfach noch um muhC und machst, was auch immer du machen willst.

    Oder meinst du eher, dass du muhC nicht mit der Funktion der Basisklasse speichern und laden kannst? - Das wird in der Tat ohne Unterstützung von C recht schwer ausser es werden für einen solchen Fall Funktionen angeboten, was ich aber irgendwie bezweifle.
    Je nachdem, woher denn der Wert kommt kannst du den ja aber auch einfach nach dem laden wieder neu berechnen (dafür die Methode einfach überschreiben deine spezifischen Sachen machen und dann die Basisklassenmethode aufrufen).

    ich bin mir nicht ganz sicher was du meinst. mir ist klar, dass ich durch vererbung auf die (public-)funktionen des eltern-elementes zugreifen kann. das ich muhC nur aus einem myC-Objekt laden kann, wäre soweit auch kein problem...ich versuche, dass was ich gerne hätte, vielleicht nochmal anders auszudrücken. also
    C ist membervariable von B, B membervariable von A, also die struktur ist sowas wie C -> B -> A .
    Ich hätte jetzt gerne eine struktur myC -> myB -> myA , wobei myC von C, myB von B und myA von A abgeleitet ist. Das Problem ist, dass die ganzen ganzen Funktionalitätet von A, die sich auf B beziehen, nicht einfach so auf myB übertragen lassen. Z.B. müsste z.B. in myA vector<B> Bs; durch vector<myB> Bs; ersetzt werden. Geht so etwas?

    drakon schrieb:

    Und jetzt noch zu etwas anderem, was mir aufgefallen ist:

    void CopyData(B tmpB) {
            /* Kopiert alles aus tmpB in sich selbst */
        }
    

    Diese Funktion klingt für mich sehr nach dem Zuweisungsoperator '='. Was mich aber eher skeptisch macht ist das Funktionsargument. Da ertellst du ja bereits eine B-Kopie und du müsstest eigentlich nur noch die Werte von tmpB und dem aktuellen Objekt tauschen.

    Stimmt wohl, das Argument sollte aber eigentlich auch eine referenz sein. Da ich diese Klassenstruktur aber nicht selbst erstellt hab, kann ich dazu nichts weiter sagen, ich werde es aber weiter leiten 😉



  • Ich hätte jetzt gerne eine struktur myC -> myB -> myA, wobei myC von C, myB von B und myA von A abgeleitet ist. Das Problem ist, dass die ganzen ganzen Funktionalitätet von A, die sich auf B beziehen, nicht einfach so auf myB übertragen lassen. Z.B. müsste z.B. in myA vector<B> Bs; durch vector<myB> Bs; ersetzt werden. Geht so etwas?

    Achso. Nein so etwas geht nicht. Dazu musst du ja die Implementierung von B und C ändern und wenn du keinen Zugriff hast, dann geht das halt so nicht. 😉

    Aber probier doch mal eher das Problem, dass du lösen willst zu beschreiben, als den Weg, wie du es lösen willst.

    Du hast diese nette Hierarchie von C->B->A, die du nicht ändern kannst. Was genau willst du jetzt machen?



  • drakon schrieb:

    Achso. Nein so etwas geht nicht.

    schade. ich fürchte dann ist mir nicht zu helfen.

    trotzdem versuche ich es nochmal.

    drakon schrieb:

    Du hast diese nette Hierarchie von C->B->A, die du nicht ändern kannst. Was genau willst du jetzt machen?

    Ich habe jetzt ein Objekt vom Typ A (nennen wir es objA), in dem ganz viele Objekte von B's gespeichert sind, und in allen B's sind nochmal ganz viele Objekte der C's.

    Zur vollständigen Charakterisierung der B's und C's fehlt aber noch etwas, nämlich noch einige Variablen, welche sich auch während der Laufzeit ändern. Diese Variablen hätte ich nun gerne direkt in den Objekten von B und C gespeichert.



  • n0wi schrieb:

    ...
    Zur vollständigen Charakterisierung der B's und C's fehlt aber noch etwas, nämlich noch einige Variablen, welche sich auch während der Laufzeit ändern. Diese Variablen hätte ich nun gerne direkt in den Objekten von B und C gespeichert.

    Aber wie drakon oben schon geschrieben hat, kannst du am objA in desen "Liste" vom Typ B auch Objekte vom Typ myB stecken. Die "Standard"-arbeiten funktionieren deshalb ja immer noch. Wenn du dann aber auf bestimmte Funktionen der neuen Klassen zugreifen willst musst du vorher casten. So sollte es doch dann funktionieren oder nicht?

    Mfg marco



  • Marc-O schrieb:

    n0wi schrieb:

    ...
    Zur vollständigen Charakterisierung der B's und C's fehlt aber noch etwas, nämlich noch einige Variablen, welche sich auch während der Laufzeit ändern. Diese Variablen hätte ich nun gerne direkt in den Objekten von B und C gespeichert.

    Aber wie drakon oben schon geschrieben hat, kannst du am objA in desen "Liste" vom Typ B auch Objekte vom Typ myB stecken. Die "Standard"-arbeiten funktionieren deshalb ja immer noch. Wenn du dann aber auf bestimmte Funktionen der neuen Klassen zugreifen willst musst du vorher casten. So sollte es doch dann funktionieren oder nicht?

    Mfg marco

    Kommt ganz drauf an, wie die Basisklassen gebaut sind. Wenn sie nicht polymorph sind, dann wird das kaum gehen (und vor allem nicht, wenn keine Zeiger im Container gespeichert werden).

    @n0wi
    Naja. Ich würde das wahrscheinlich so machen, dass ich die Zusatzinformationen noch seperat halte. Wenn es sein muss wird das ganze noch ein wenig gewrapt, damit dich von aussen nur um etwas kümmern musst.
    Sprich du baust dir deine myA, myB und myC und hältst dort drin nur das, was du noch brauchst (kann natürlich auch mit nur einer Klasse oder geschehen) und dann sorgst du dafür, dass das alles immer schön synchron bearbeitet wird.



  • Kommt ganz drauf an, wie die Basisklassen gebaut sind. Wenn sie nicht polymorph sind, dann wird das kaum gehen (und vor allem nicht, wenn keine Zeiger im Container gespeichert werden).

    beides ist int der tat nicht gegeben.

    so wie drakon es unten beschreibt, wird es im moment im prinzip auch gemacht. ist natürlich alles nicht sehr handlich. die information, dass es nicht ohne weiteres hinhaut, bringt mich aber schon sehr viel weiter.

    Also, erstmal vielen Dank für eure Mühe! Wahrscheinlich werde ich mich zu gegebener Zeit nochmal melden 😉



  • Naja. Am saubersten wäre es die die ursprünglichen Klassen anzupassen.


Log in to reply