Muss ich Dtor virtuell definieren?
-
Hi,
ich habe so eine Klasse:
class ResourceOwner { public: virtual void onResourceCreated(Resource* r) = 0; };Mehr brauch ich eigentlich nicht. Nur kann es absolut sein, dass ResourceOwner Subklassen über einen Basisklassenzeiger ResourceOwner* gelöscht werden. Also muss ja der Dtor virtuell sein.
Meine Fragen:
Wenn ich jetzt in ResourceOwner einfach nur schreibe:virtual ~ResourceOwner();dann gibt das doch einen Linkerfehler, oder?
also muss ich schreibenvirtual ~ResourceOwner() { }Wenn ich den Dtor explizit definiere, muss ich dann auch den Ctor definieren?
-
Alex~ schrieb:
Wenn ich den Dtor explizit definiere, muss ich dann auch den Ctor definieren?
Nein
-
Alex~ schrieb:
Wenn ich jetzt in ResourceOwner einfach nur schreibe:
virtual ~ResourceOwner();dann gibt das doch einen Linkerfehler, oder?
Ja, es sei denn du schreibst die Definition in eine .cpp-Datei.
Alex~ schrieb:
also muss ich schreiben
virtual ~ResourceOwner() { }Auch eine Möglichkeit.
Alex~ schrieb:
Wenn ich den Dtor explizit definiere, muss ich dann auch den Ctor definieren?
Nein.
-
Ja, wenn du vorhast, abgeleitete Klassen über einen Basis-Zeiger freizugeben, brauchst du einen virtuellen Destruktor (selbst wenn der (scheinbar) leer ist).
Und nein, wenn sie ihn nicht unbedingt für ihre eigene Arbeit benötigt, braucht die Klasse keinen selbstdefinierten Konstruktor.
-
nein musst du nicht. (kapitel 5 oder 6 ind er aktuellen auflage von effective c++ programming von Scott Meyers)
es gibt:
a) konstruktoren -> standardkonstruktor (d.h. Ctor ohne parameter), konstruktoren mit parametern
b) copy constructor (wird aufgerufen wenn du ein objekt mit einem anderen objekt gleichen typs initialisierst)
c) zuweisungsoperator (wird genutzt wenn man einem objekt ein anderes gleichen typs zuweisen will)
d) destruktor (wird aufgerufen wenn das objekt seinen gültigkeitsbereich verlässt)so, und alle 4 dieser typen sind beim automatischen generieren durch den compielr voneinander unabhängig. die *toren in diesen 4 typen aber nicht, wenn du einen davon deklarierst werden keine anderen erzeugt
beispiel:
schreibst du in deiner klasse nur einen konstruktor der 5 parameter erwartet, passiert folgendes:
- nur dieser 5parametrige konstruktor ist da
- der copy Ctor wird durch den compiler generiert
- der zuweisungsoperator wird durch den compiler generiert
- der destruktor wird durch den compiler generiertschreibst du aber den destruktor und den zuweisungsoperator, kommt das raus
- es wird ein standard konstruktor generiert
- es wird ein copy ctor durch den compiler generiert
- der zuweisungsoperator ist durch dich erzeugt
- der destruktor auchund dazu gibst es noch die regel der grossen 3, die besagt, dass:
Wenn entweder der Kopierkonstruktor oder der Zuweisungsoperator oder der Destruktor selbst geschrieben werden müssen, müssen die jeweils anderen beiden auch selbst geschreiben werden.
Das meint, dass klassen die komplexere typen (wie zum beispiel zeiger) innehaben und nicht einfach beim kopieren 1 zu 1 kopiert werden können/dürfen, einen vom programmierer definierten copy ctor, zuweisungsoperator und einen destruktor haben müssen.
-
@Skym0sh0:
Dein Posting ist sehr hilfreich, danke
Allerdings glaube ich, dass es eine kleine Abweichung gibt. Ich habe gerade eine Klasse definiert die so aussah:
class Foo { private: Foo(const Foo & rhs); Foo& operator=(const Foo& rhs); };Nach deiner Beschreibung sollte jetzt ja ein Default Ctor erstellt werden, da ja kein Ctor mit Parametern definiert wurde. Tut der Compiler aber offenbar nicht, denn hier findet er keinen Ctor:
Foo* f = new Foo; // Fehler. Findet keinen Default CtorOffenbar hängen der Default Ctor, Ctor mit Parametern und der Copy Ctor also doch zusammen. Definiert man irgend einen von den 3 Typen, scheint der Compiler die andren nicht mehr zu generieren.
-
Der selbstdefinierte Copy-Konstruktor gilt in dem Zusammenhang (vermutlich) auch als ein "Konstruktor mit Parameter", von daher greift dort auch die erstgenannte Konstellation - der Compiler generiert keinen eigenen Default-Konstruktor.
-
Sobald ein Konstruktor deklariert wird wird kein impliziter Default Konstruktor erzeugt:
12.1/5 schrieb:
A default constructor for a class X is a constructor of class X that can be called without an argument. If
there is no user-declared constructor for class X, a default constructor is implicitly declared.