Decorator Pattern: Nutzung der abstrakten Klasse



  • Hallo,

    Ich versuche gerade das Decorator Pattern mit C++ zu realisieren.

    Ich möchte folgenden Bauplan umsetzen:

    //Abstrakte BasisKlasse 
    class Basis{
       virtual void ichMache()=0;
    }
    
    // Konkrete Basisklasse
    
    class Konkret: public Basis{
       ichMache(){
       //etwas
       }
    }
    
    //Abstrakte DecoratorKlasse
    
    class Decorator : public BasisKlasse{
    
    protected:
      Basis wrappedObject; // Genau hier beginnen die Probleme
    }
    
    // Konkreter Decorator
    class ConcrectDecorator : public Decorator{
    
    ichMacheNochMehr(){
       this->wrappedObjekt->IchMache();
       //Mache noch meh!
    }
    

    Nun ist es ja nicht möglich (oder doch) eine abstrakte Klasse als Member in der ebenfalls Abstrakten Klasse Decorator zu deklarieren.
    Der Compiler meldet:

    Feld »wrappedInDevice« kann nicht als vom abstrakten Typ »BasisKlasse« deklariert werden
    Anmerkung:   denn die folgenden virtuellen Funktionen sind rein innerhalb »BasisKlasse«:	virtual void ichMache()
    

    Die Basis-Klasse bzw. die konkrete Implementation davon muss doch im Decorator irgendwie gekapselt werden, damit man sie im konkreten Decorator nutzen kann.

    Wo liegt der Überlegungsfehler?

    M



  • Du versuchst von einer abstarkten Basisklasse eine Instanz zu erzeugen, aber das geht nicht! Das ist der Sinn von abstrakten Basisklassen, sie dienen nur als Basis. Man darf nur von Ihnen ableiten.

    class Decorator : public BasisKlasse{
    
    protected:
      Basis& wrappedObject; // Referenz (oder Zeiger) benutzen
                            // und dann Objekt vom Typ Konkret zuweisen.
    }
    

  • Administrator

    Du kannst kein abstraktes Objekt erstellen, aber eine Referenz oder, was hier wohl sinnvoll wäre, einen Zeiger auf ein abstraktes Objekt.

    Übrigens, ich würde Klassenmember immer als private deklarieren. Ich habe noch keinen sinnvollen Anwendungsfall gesehen, welcher wirklich public oder protected Klassenmember erfordert hat.
    Mach lieber zugehörige Setter und Getter, welche du auch in Kindklassen benutzt, so ist die Kontrolle über die Variable einheitlicher, bzw. eindeutiger. Für die Fehlersuche ist das sehr hilfreich.

    Grüssli



  • Danke Roger Wilco und Dravere.

    Eure Posts haben mir weiter geholfen. Der Vollständigkeit halber poste ich nocht die korrigiert Version:

    //Abstrakte BasisKlasse
    class Basis{
       virtual void ichMache()=0;
    }
    
    // Konkrete Basisklasse
    
    class Konkret: public Basis{
       ichMache(){
       //etwas
       }
    }
    
    //Abstrakte DecoratorKlasse
    
    class Decorator : public BasisKlasse{
    
    private:
      Basis & wrappedObject  ; // NEU: eine Referenz! -> Problem gelöst
    }
    
    // Konkreter Decorator
    class ConcrectDecorator : public Decorator{
    
    ichMacheNochMehr(){
       this->wrappedObjekt.IchMache();
       //Mache noch meh!
    }
    

    Betreffend der Bemerkung von Dravere, auf Protected zu verzichten:
    Auf http://www.willemer.de/informatik/cpp/cpperben.htm habe ich folgendes gelesen:

    Eine abgeleitete Klasse kann nicht auf die privaten Elemente der Basisklasse zugreifen.

    Das würde heissen, dass meine konkreten Decorators nicht auf das wrapped-Object zugreifen können. D.h. muss ich doch die Member-Variable als protected deklarieren. Oder liege ich da falsch?


Anmelden zum Antworten