2016-08-04 39 views
0

Ich weiß über Virtual Class, dass sie nicht, nun instanziiert werden kann ich eine Frage zu einem Fall darüber haben, nehmen wir eine reine abstrakte Klasse wie unten haben:Wie verwende ich eine abstrakte Klasse in einer anderen Klasse (oder einer Klasse)?

class Color{ 
public: 
    Color(); 
    virtual string getName()=0; 
    ~Color(); 
}; 

und 2 Klasse vererbte Form es:

class Blue:public Color 
{ 
public: 
    Blue(); 
    ~Blue(); 
    string getName(); 
}; 

class Red:public Color{ 
public: 
    Red(); 
    ~Red(); 
    string getName(); 
}; 

und dritte Klasse wollen Color Klasse als Konstruktorparameter und Datenelement verwenden:

class Foo{ 
public: 
    Foo(); 
    Foo(Color&); 
    ~Foo(); 
    void draw(Color&); 
private: 
    Color* co; 
}; 

und seine Umsetzung:

Foo::Foo():co(new Color()){ 
} 

Foo::Foo(Color &c):co(new Color(c)){ 
} 
Jetzt

, weiß ich über diesen Teil new Color() und new Color(c) in diesem Fall falsch ist, aber ich möchte nur eine Art Color zu übergeben Foo und nicht direkt Blue oder Red mit verwenden, als Parameter.

Was ist eine Lösung? Muss ich überladen oder etwas anderes benutzen? und für Methode draw habe ich irgendein Problem? und ich lese über Entwurfsmuster, hilft es mir über diesen Fall?

tnx für Ihre Antwort.

+0

"co" als Nullzeiger im Standardkonstruktor initialisieren? –

+0

@Joachim Pileborg Nein, ich habe es nicht benutzt. – mehdi

Antwort

1

Für den Konstruktor, der eine Farbe &, Sie entweder speichern in Farbe einen Verweis oder Zeiger auf die übergeben kann dauert, wenn Sie kann sein gehen weiterhin sicher sein, existieren, oder ein intelligenter Zeiger könnte für Ihre Verwendung geeignet sein, wenn Sie einen Zeiger auf eine zuvor vorhandene Farbe speichern und sicherstellen möchten, dass er nicht zu früh gelöscht wird. Oder wenn Ihre Klasse eine eigene Kopie der Farbe haben soll, können Sie das Klonmuster verwenden. Ein Kopierkonstruktor für Farbe müsste eine Farbe zurückgeben (keine davon abgeleitete Klasse), was nicht möglich ist, da die Farbe abstrakt ist. Clone wäre eine virtuelle Farbfunktion, die einen Farbzeiger zurückgibt. In abgeleiteten Klassen wird implementiert, um eine neue Instanz des abgeleiteten Typs zurückzugeben.

class Color 
{ 
    public: 
    virtual Color* Clone() const = 0; 
}; 

class Red : public Color 
{ 
    public: 
    virtual Red* Clone() const 
    { 
     return new Red(*this); // updated to use copy constructor 
    } 
}; 

Foo::Foo(const Color& c) : co(c.Clone()) 
{} 

Für die Standard-foo Konstruktor müssen Sie wählen, ob sein OK für foo der Farbe * Mitglied null zu sein, wenn es dann in nullptr passieren wird, wie vorgeschlagen. Wenn nicht, können Sie eine Standardfarbe auswählen, um die Farbe * zu initialisieren. Hinweis Foo behält immer noch eine Farbe * nicht ein Rot *. Sie konnten die Standardfarbklasse mit einer typedef oder mit Anweisung angeben, um sicherzustellen, dass Sie den Standard definieren nur einmal: -

using DefaultColour = Red; 
Foo::Foo() : co(new DefaultColour()) {} 

Oder einfach nicht gibt Foo ein Standard-Konstrukt - darauf bestehen, dass eine Farbe

vorgesehen ist
+0

Tnx sehr für Ihre ausgezeichnete Analyse, ich bin neu in C++ und Sie sagten über Smart Pointer, können Sie mir sagen, wie verwende ich es, wenn Sie mögen und Sie sagte über Standard-Farbklasse mit Typedef oder mit Anweisung wie mache ich das? ist die DefaultColour-Klasse? – mehdi

+1

in Bezug auf die Standardfarbe - das ist die using-Anweisung im obigen Beispiel. (Typdef wäre eine ältere Art, dasselbe zu tun). Es ist ein Alias ​​für Ihre Klasse, in diesem Fall sage ich, dass der Standardwert rot ist. Ich kann dann auf DefaultColour verweisen, wo immer ich es brauche. Aber wenn ich den Standard auf Blau ändere, gibt es nur eine Zeile, die geändert werden muss Linie mit der Verwendung). Es trägt auch dazu bei, dass der Code selbstdokumentiert wird, wenn Sie DefaultColor verwenden, zeigt es an, dass Sie es verwenden, weil es der Standard ist, nichts Besonderes daran, dass es rot oder blau ist. – ROX

+1

in Bezug auf die Smart Pointer - am besten, um sie nachzuschlagen, konnte ich nicht alles abdecken, und wie Sie es verwenden müssten, hängt davon ab, was mit dem Farbobjekt passiert, das Sie in den Foo-Konstruktor übergaben. Der Grund, warum ich es erwähne, ist, dass wenn Sie einen Zeiger auf ein Objekt speichern, das an den Konstruktor übergeben wurde, das Objekt nicht gelöscht werden soll und die foo-Klasse immer noch auf Speicher zeigt, wo das Objekt nicht mehr existiert war früher. – ROX

1

Initialisieren Sie Mitglied Zeiger auf nullptr:

Foo::Foo() : co(nullptr) {} 
Foo::Foo(Color &c) : co(nullptr) {} 
+1

Sieht aus wie eine mögliche Lösung für den Standardkonstruktor, aber eher seltsam, eine Version des Konstruktors zu haben, die eine Farbe annimmt und sie ignoriert. – ROX