Wieder ein OOP Problem



  • Folgende Klassen angenommen:

    class ABase {
    public:
    	void do1() { std::cout << "do1"; }
    };
    
    class ADerived : public ABase {
    public:
    	void do2() { std::cout << "do2"; }
    };
    
    class BBase {
    public:
    	BBase(ABase* a_) : a(a_) {}
    	void print1() { a->do1(); }
    
    protected:
    	ABase* a;
    };
    
    class BDerived : public BBase {
    public:
    	BDerived(ADerived* a_) : BBase(a_) {}
    	void print2() { a->do2(); }
    };
    

    Im Endeffekt besteht also immer eine Beziehung zwischen den abgeleiteten Klassen: BBase braucht Funktionalität aus ABase und BDerived wiederum welche (do2) aus ADerived. Das Problem ist ja aber offensichtlich, dass in der BBase-Klasse schon der ABase-Typ feststeht. Wie kann man dem am besten begegnen (irgendein Pattern?)?

    €: Virtuelle und leer implementierte Methoden sollten nicht vorkommen.



  • Kommt drauf an, was Du willst.

    Zuerst würde ich vorschlagen statt do1 und do2 eine virtuelle Funktion do zu implemtieren. Die abgeleitete Klasse überschreibt dann einfach das Verhalten von ABase. Da Du im Konstruktor sicherstellst, das Du jeweils die richtige abgeleitete Klasse bekommst, kannst Du ruhigen Gewissens die virtuellen Methoden auch auf dem Basisklassenzeiger aufrufen.

    Wenn das keine Lösung für Dein Problem ist, (z.B. Du brauchst tatsächlich neue Methoden in der abgeleiteten Klasse - Designfehler?) kannst du natürlich immer einen dynamic_cast vor dem Aufruf von do2 machen. Du bist ja sicher, das Du ein objekt der abgeleiteten Klasse hast. Besser wäre es vielleicht einfach einen zweiten Zeiger auf ADerived in BDerived zu definieren.

    Wenn das immer noch nicht Dein Problem löst, kannst Du Dir noch das Visitor Pattern anschauen.

    DJohn



  • Danke erstmal für die Antwort. Also Designfehler kann man mir nicht vorwerfen, bin eben grad dabei das gröbste wieder auf einen einigermaßen ordentlichen Weg zu bringen.

    Also do als virtuelle Methode definieren geht so nicht, weil die beiden Methoden (ja der Name war jetzt unglücklich gewählt) nichts miteinander zu tun haben. Das mit dem dynamic_cast und dem zweiten Zeiger hab ich mir auch überlegt, aber da dachte ich mir noch es müsste eine elegante Lösung geben.



  • Hi!

    class BBase {
    public:
        BBase(ABase* a_) : a(a_) {}
        void print1() { GetA()->do1(); }
        ABase *GetA() const { return a; }
    
    protected:
        ABase* a;
    };
    
    class BDerived : public BBase {
    public:
        BDerived(ADerived* a_) : BBase(a_) {}
        void print2() { GetA()->do2(); }
        ADerived *GetA() const { return ( ADerived *)BBase::GetA(); }
    };
    

    So sollte das gehen, nicht?



  • Hmm, ja das läuft halt auf diesen Cast hinaus. Nicht schön, sollte aber funktionieren.


Log in to reply