"Gekoppelte" Vererbung?



  • Hallo zusammen,

    ich habe eine Frage, wie man am besten folgendes Problem löst (oder ggf. ganz anders macht).

    Vielleicht am besten gleich Code, der das illustriert. Weitere Member, die hier nichts zur Sache tun, habe ich im Sinne eines Minimalbeispiels weggelassen:

    struct BaseValue
    {
    	BaseValue(size_t res);
    	BaseValue();
    	virtual ~BaseValue();
    	size_t resolution;
    	std::vector<double> values;
    };
    
    struct DerivedValue : public BaseValue
    {
    	DerivedValue(size_t additionalParam, size_t res);
    	DerivedValue();
    	~DerivedValue();
    	// resolution aus Basisklasse
    	// values aus Basisklasse
    	size_t addParam;
    	std::vector<double>  paramvals;
    };
    
    struct BaseManagement
    {
    	BaseManagement();
    	BaseManagement(std::vector<std::string> input);
    	virtual ~Collection();
    	size_t nbofentries;
    	std::vector<BaseValue> entries;
    	void someFunction(BaseValue foo);
    };
    
    struct DerivedManagement : public BaseManagement
    {
    	DerivedManagement(std::vector<std::string> input);
    	~DerivedManagement();
    	// nbofentries aus Basisklasse
    	// entries aus Basisklasse
    	size_t nbofparams;
    	std::vector<DerivedValue> entries;  /// Hier ist das Problem:
    // DerivedManagement hat ja dann zusätzlich den std::vector<BaseValue> entries
    // aus der Basisklasse! Ich möchte aber, dass es hier nur einen
    // std::vector<DerivedValue> gibt, der "entries" aus der Basisklasse ersetzt.
    };
    

    Wie kann man so eine Art "gekoppelte" Vererbung erreichen? Ich möchte, dass DerivedManagement auf der DerivedValue-Klasse aufsetzt, weiß aber nicht, wie ich die Vererbung des std::vector<BaseValue> entries überschreiben kann.

    Oder ist das Design einfach Mist und ich sollte das ganz anders machen?

    Viele Grüße vom
    inharator



  • Wie wäre es, wenn du die Basisklasse templatisierst?

    template<class T>
    struct BaseManagement
    {
        std::vector<T> entries;
    };
    
    struct DerivedManagement : public BaseManagement<DerivedValue>
    {
    };
    


  • Ebtweder so wie mein Vorredner oder:

    struct AbstractManagement
    {
        AbstractManagement();
        AbstractManagement(std::vector<std::string> input);
        virtual ~AbstractManagement();
        size_t nbofentries;
    };
    
    struct BaseManagement : public AbstractManagement
    {
        BaseManagement(std::vector<std::string> input);
        ~BaseManagement();
        std::vector<BaseValue> entries;
        void someFunction(BaseValue foo);
    };
    
    struct DerivedManagement : public AbstractManagement
    {
        DerivedManagement(std::vector<std::string> input);
        ~DerivedManagement();
        std::vector<DerivedValue> entries;
        void someFunction(DerivedValue foo);
    };
    


  • Danke! Ich habe die Lösung von daddy_felix ausprobiert und es funktioniert so wie es soll. Eigentlich simpel, bin aber nicht drauf gekommen 🙂

    @MichelRT: Auch wenn Dein Vorschlag für mich zu spät kam, ist es gut, auch eine zweite Lösungsmöglichkeit zu kennen.

    Viele Grüße vom
    inharator



  • Achtung: die Template-Lösung hat aber auch Nachteile.
    Du hast damit 2 Basisklassen. Es ist somit unmöglich polimorphes Verhalten zu nutzen. Solange Du immer die konkreten Klassen verwendest ist das aber egal.
    Wenn Du aber eine Fabrikmethode verwendest die Dir Deine Managment-Objekte erzeugt und die dann als Referenz oder Zeiger auf die Basisklasse zurückliefert funktioniert die Template-Lösung so nicht.



  • Man könnte auch eine non-Template Basisklasse machen die einen vector<unique_ptr<BaseValue>> hat.

    Oder vor dem BaseManagement Template noch eine non-Template Basisklasse einziehen, die Dinge die vom konkreten Value-Type abhängig sind dann ggf. über virtuelle Funktionen an das BaseManagement Template delegiert.


Log in to reply