2015-07-08 8 views
6

Ich dachte in der Theorie die Antwort auf diese Frage war ja.Kann eine abgeleitete Klasse nicht kopierbar gemacht werden, indem man den Kopierkonstruktor/operator in der Basisklasse als privat deklariert?

In der Praxis scheint jedoch mein Compiler (VS2010) in der folgenden Situation nicht zu klagen: Ich habe eine abstrakte Basisklasse, die eine gemeinsame Schnittstelle (noch keine Datenelemente) und verschiedene davon abgeleitete Sub- und Subsubclasses bereitstellt.

class Base 
{ 
public: 
    Base() {} 
    virtual ~Base() {} 

    virtual void interfaceFunction1() = 0; 
    virtual void interfaceFunction2() = 0; 
private: 
    Base(const Base&);   // all derived classes should be uncopyable 
    Base& operator=(const Base&); 

    // no data members 
}; 

Mein Compiler fand es unproblematisch, auch voll Kopierkonstruktoren in sub- oder subsubclasses zu implementieren.

Wie kann ich sicherstellen, dass jede von Base abgeleitete Klasse nicht kopierbar ist?

edit: Wenn ich gut verstehen, das ist genau das, was Scott Meyers 6 von Effective C in näheren Erläuterungen ++ (3. Auflage, 2005) mit seiner Idee der Klasse Uncopyable (nur erweitert hier auf eine vollständige Schnittstelle Klasse). Was macht seine Idee aus? (Ich weiß, dass er privat erbt, aber das sollte kein Problem darstellen)

+0

Kann ein Dummy-Datenelement hinzugefügt werden. –

+1

Haben Sie andere Compiler getestet? Auch eine abgeleitete Klasse zu präsentieren wäre nett;) (eigentlich eher etwas von einem kompilierbaren Beispiel.) – luk32

+0

Was ist der Nutzen einer reinen Funktion, die nicht virtuell markiert ist? –

Antwort

3

Dies sollte verhindern, dass der Compiler einen Kopierkonstruktor für abgeleitete Klassen generiert, die nicht explizit deklarieren. Nichts hindert jedoch eine abgeleitete Klasse daran, explizit einen Kopierkonstruktor zu deklarieren, der etwas anderes tut, als den Kopierkonstruktor Base aufzurufen.

Es gibt keine Möglichkeit sicherzustellen, dass abgeleitete Klassen instanziierbar, aber nicht kopierbar sind.

+0

Könnte es eine Lösung sein, um Base() privat zu machen? (Aber dann würde ich auf statische Fabrikmethoden zurückgreifen müssen, was wie eine Menge Ärger klingt, nur um diese Klassen unkopierbar zu machen) –

+0

@TG_ Nein, das würde nicht funktionieren. Wenn Sie * all * 'Base'-Konstruktoren' private' belassen, ist die abgeleitete Klasse nicht in der Lage, sich selbst zu initialisieren (nicht durch Kopieren, nicht standardmäßig, auf keine andere Weise).Wenn Sie einen Base-Konstruktor zugänglich machen, kann die abgeleitete Klasse das in ihrem eigenen copy-ctor verwenden. – Angew

1

Anstatt den Kopierkonstruktor/Operator als privat zu deklarieren, deklarieren Sie sie als gelöscht. Die Deklaration des Kopierkonstruktors/-operators als privat ist nicht die beste Lösung, um die abgeleiteten Klassen nicht kopierbar zu machen. Wenn Sie möchten, dass die Basisklasse vollständig nicht kopierbar ist, deklarieren Sie den Kopierkonstruktor/Operator als d löschen d als Kopie kann immer noch innerhalb der Elementfunktionen von Base als private Mitglieder sind zugänglich für die Klassenfunktionen. Sie können das C++ 11 Merkmal löschen verwenden:

Base(const Base&) = delete; // copy constructor 
Base& operator=(const Base&) = delete; // copy-assignment operator 

Aber erklärt Copykonstruktor/Betreiber als Privat auch wie Recht lange, wie Sie diese Kopie noch bewusst sind, Platz innerhalb der Elementfunktionen übernehmen kann Basis.

+1

macht sie privat und deklariert als gelöscht hat den gleichen Effekt –

+0

@ BЈovић Nicht unbedingt, dass sie privat machen nicht gewährleistet, dass Objekte dieses Typs nicht kopierbar sind. Wenn wir sie als gelöscht deklarieren, kann keine Kopie stattfinden. Element 11 von Effective Modern C++ gibt an, dass Code, der Mitglieds- und Freundesfunktionen enthält, nicht kompiliert werden kann, wenn er versucht, eine gelöschte Elementfunktion zu verwenden. Wenn Sie sie als privat deklarieren, bedeutet dies, dass Code innerhalb von Member-Funktionen und Freunden dieser bestimmten Klasse diese verwenden kann und die Verknüpfung aufgrund fehlender Funktionsdefinitionen fehlschlägt. –

+1

Ein Standard-Kopierkonstruktor erstellt ein neues Basisobjekt und versucht nicht, es zu kopieren. Dieser Ansatz funktioniert also nicht, wenn die abgeleitete Klasse den Standardkopiekonstruktor verwendet und die abgeleitete Klasse kopierbar ist, die Basis dagegen nicht. –

Verwandte Themen