Ich versuche zu verstehen, was der Autor in 3.3.4 Suppressing Operations
in seinem neuen Buch (TCPL 4. Ausgabe) vorschlägt, ohne Erfolg.
Auszug aus dem Buch
%Vor%Verwenden der Standardkopie oder -verschiebung für eine Klasse in einer Hierarchie ist In der Regel eine Katastrophe: Nur einen Zeiger auf eine Basis gegeben, tun wir einfach nicht wissen, welche Mitglieder die abgeleitete Klasse hat (§3.3.3), so können wir nicht wissen, wie um sie zu kopieren. Also, das Beste, was zu tun ist, ist normalerweise zu löschen Standard Kopier- und Verschiebeoperationen; das heißt, standardmäßig zu beseitigen Definitionen dieser beiden Operationen:
Nun wird ein Versuch, eine Form zu kopieren, vom Compiler abgefangen. Wenn du müssen Sie ein Objekt in einer Klassenhierarchie kopieren, schreiben Sie eine Art von Klon Funktion (§22.2.4).
Der folgende Code kompiliert beispielsweise nicht mit Shape(const Shape&) = delete;
, da die Funktion clone()
den Kopierkonstruktor Shape
aufruft.
Wenn Sie nur einen Zeiger auf ein Shape
haben, dann können Sie möglicherweise keine Kopie der tatsächlichen Implementierung erstellen - es wird (wahrscheinlich) größer sein, so dass Ihre Kopie "geschnitten" wird. In Ihrem Beispiel hat Circle
eine zusätzliche int a
; das ist nicht Teil der Klasse Shape
- die wäre verloren, wenn du einfach ein Shape
klasse Objekt kopierst, ohne zu wissen, dass es ein Circle
ist (und der ganze Punkt des Polymorphismus ist, dass du nicht "wissen" sollst) "welches Objekt ist welcher Typ, wenn es in generischen Funktionen damit zu tun hat"
Um Probleme zu vermeiden, die durch versehentliches Verwenden von etwas wie:
verursacht werden %Vor%ist es besser, die Operatoren zu "löschen", die Ihnen erlauben, das zu tun
Da jedoch der Kopierkonstruktor für den von Ihnen beschriebenen Fall benötigt wird, besteht eine Lösung darin, protected
zu machen - das schützt vor etwas anderem als einer abgeleiteten Klasse, die es verwendet, und funktioniert korrekt.
Dank robson unten (und auch nachts) ist die Lösung klar, einen Copy-Konstruktor in Circle
zu machen. Nur weil Sie keinen für Shape
haben, heißt das nicht, dass Sie keinen in der abgeleiteten Klasse haben können:
Der Grund, warum versucht wird, den Shape
-Kopierkonstruktor zu verwenden, liegt darin, dass Sie in Ihrer eigenen Klasse keinen haben. Du solltest!
Sie könnten auch tun (wie Robson erklärte):
%Vor% Und brauche keinen Kopierkonstruktor. Beide Lösungen lösen die "Sie versuchen, eine gelöschte Shape(const Shape &) constructor
zu verwenden. Es ist wirklich offensichtlich, sobald Sie es sehen.
Er meinte, dass es schlecht sei, sie von außen zugänglich zu machen, wegen potentieller Objekt-Slicing-Probleme. Wenn Sie die Klasse nicht klonbar machen wollen, reicht das Löschen nicht aus. Andernfalls können Sie sie nur so schützen, dass sie nur innerhalb von clone()
und den nachfolgenden Zugriffen verfügbar ist.