linker-Fehler bei abstraktem virtuellen Dtor
-
kartoffelsack schrieb:
funzen tuts, wenn ich
virtual ~Foo()=0{};
schreibe.Nein, das ist verboten. entweder körper oder =0, beides geht nicht.
aber einvirtual ~Foo() =0;
Foo::~Foo() {}
wäre korrekt.Das heißt ja, dass =0 hinter einem Dtor eigentlich keinen Sinn macht
Jede KLasse muss einen Dtor haben. Ohne geht es nicht (ist wie mit dem Ctor ;))
Wenn du den Dtor aber rein virtuell machst, dann ist die Klasse abstrakt.
-
Wenn du den Konstruktor pure virtual machst, ist die Klasse nicht abstrakt, sondern unbrauchbar, da der Konstruktor der abgeleiteten Klasse den Konstruktor der Basisklasse aufruft. Zum Beispiel gibt
#include <iostream> struct A { virtual ~A() { std::cout << "A::~A" << std::endl; } }; struct B : public A { virtual ~B() { std::cout << "B::~B" << std::endl; } }; int main() { A *p = new B; delete p; }
Bei Ausführung
B::~B A::~A
aus. Abstrakt ist die Klasse, wenn eine Methode pure virtual ist.
-
0xdeadbeef schrieb:
Wenn du den Konstruktor pure virtual machst
Du meinst Destruktor, oder?
Abstrakt ist die Klasse, wenn eine Methode pure virtual ist.
Der Dtor kann durchaus auch pure virtual sein.
Dennoch braucht er einen Körper.
-
Was macht das denn?
~Foo() =0;
-
the_alien schrieb:
Was macht das denn?
~Foo() =0;
einen syntax fehler.
wenn du abervirtual ~Foo() = 0;
meinst:
das macht den Dtor rein virtuell und somit die Klasse abstrakt.
-
Ja meinte ich. Danke.
-
Also nochmal:
Wenn ich
virtual ~Foo() = 0;
schreibe, dann krieg ich den Linker-Fehler (bei VC 7.1, nicht bei BCB 5.5).
Wenn ich Euch jetzt richtig versteht müsste das aber funzen?Den Linker-Fehler krieg ich nicht mehr, wenn ich
virtual ~Foo(){};
oder
virtual ~Foo()=0{};
schreibe, wobei zweiteres komisch aussieht und, wenn ich Euch richtig verstehe eigentlich falsche syntax ist (aber von VC7.1 und BCB 5.5, problemlos gefressen wird) - aber egal. Was micht interessiert ist der pure virtual dtor.
-
Mein BCB5 wirft bei deiner ersten Variante einen Linkerfehler und bei der dritten einen Compilerfehler (geht also beides nicht). Bei der zweiten Variante ist die Klasse nicht abstrakt (es sei denn es ist noch eine abstrakte Funktion drin).
Also normalerweisevirtual ~Foo()=0;
und dann später
Foo::~Foo() {}
Siehe auch "Effektiv C++ programmieren" Lektion 14.
-
kartoffelsack schrieb:
Den Linker-Fehler krieg ich nicht mehr, wenn ich
virtual ~Foo(){};
oder
virtual ~Foo()=0{};
schreibe, wobei zweiteres komisch aussieht und, wenn ich Euch richtig verstehe eigentlich falsche syntax ist (aber von VC7.1 und BCB 5.5, problemlos gefressen wird) - aber egal. Was micht interessiert ist der pure virtual dtor.
Shade Of Mine schrieb:
kartoffelsack schrieb:
funzen tuts, wenn ich
virtual ~Foo()=0{};
schreibe.Nein, das ist verboten. entweder körper oder =0, beides geht nicht.
aber einvirtual ~Foo() =0;
Foo::~Foo() {}
wäre korrekt.was ist unklar?
-
was ist unklar?
Mit Braunsteins aussage ist mir jetzt gleich garnixmehr klar
Also normalerweise
virtual ~Foo()=0;
und dann später
Foo::~Foo() {}
Das heißt also, wenn ich
~Foo()=0;
schreibe, muss ich den Dtor trotzdem implementieren?
-
Ja.
Das hat Shade aber auch schon gesagt.
-
ok, jetzt hab ich's kapiert. Und außerdem hab ichs kapiert, dass ihr das schon gesagt habt
Danke!
-
Hallo,
das ist imo so ein Problem, dass nur deshalb existiert, weil es so unendlich viele schlechte C++ Einsteigerbücher gibt, in denen selbsternannte Experten entweder krampfhaft versuchen ein Thema zu vereinfachen oder aber selbst schlicht und einfach keine Ahnung haben.Beispiel zum Thema:
Schildt schreibt in seinem grausiligen "C++ Entpackt":Eine rein virtuelle Funktion ist eine virtuelle Funktion, die in der Basisklasse keine Definition besitzt.
Klasse. Kurz, knapp und KÄSE!
Aber "C++ Entpackt" ist nicht das einzige Buch in dem die Eigenschaft rein-virtuell fälschlicherweise so definiert wird.
Einige versuchen später noch mit Gewalt die "Ausnahme rein virtuelle Dtor" unterzubringen, aber da haben die meisten bereits den falschen (und kürzeren) Merksatz abgespeichert. Da ist es doch kein Wunder, dass am Ende hauptsächlich eins übrig bleibt: Verwirrung.Imo ist das ein typisches Beispiel für eine Situation wo man ein komplexes Feature lieber etwas umfangreicher und dafür korrekt (muss ja nicht vollständig sein) als einfach und falsch einführen sollte.
-
Wieder was gelernt. Die Verwirrung hat mich zwischenzeitlich auch schon erwischt.
Aber: warum ist das eigentlich so gelöst worden? Wenn ich eine rein virtuelle Funktion mache, dann will ich in der Regel erzwingen, das jemand, der von meiner Klasse ableitet, gezwungen wird, diese Funktion zu implementieren. Wenn ich aber jetzt mal das obige Beispiel mit dem virtuellen Dtor meinem VC7.1 vorsetze, so meckert er nicht, wenn ich von der abstrakten Basisklasse ableite und keinen eigenen Dtor schreibe.
Warum das dann also?
-
Shade Of Mine schrieb:
Nein, das ist verboten. entweder körper oder =0, beides geht nicht.
Sicher?
#include <iostream> class Foo { public: virtual void whatever() = 0; }; class Bar : public Foo { public: virtual void whatever(); }; void Foo::whatever() { std::cout << "world!\n"; } void Bar::whatever() { std::cout << "hello\n"; Foo::whatever(); } int main() { Bar test; test.whatever(); }
-
finix schrieb:
Sicher?
Ja.
Mir kommt es so vor, als würden meine Beiträge hier nicht genau gelesen werden.
virtual void foo() = 0 {}
geht nicht.aber
virtual void foo() = 0;
void Foo::foo() {}
geht schon.
-
Shade Of Mine schrieb:
Mir kommt es so vor, als würden meine Beiträge hier nicht genau gelesen werden.
Ganz genau.
Sorry, sah auf die schnelle so aus als wäre der Code nur zur Unterstreichung der Aussage "entweder körper oder =0" gemeint.
-
class foo { public: virtual ~foo()=0; virtual void x()=0; }; foo::~foo() {} // wenn foo::~foo() nicht implementiert ist => link-fehler // macht für mich sinn da automatisch von abgeleiteten klassen aufgerufen void foo::x() {} // pure virtual aber trotzdem implementiert ( das war neu für mich ) class bar :public foo { public: //virtual ~bar(){} // muss nicht implementiert werden obwohl foo::~foo() als pure virtual deklariert ??? // andererseits macht es auch keinen sinn die implementation eines dtor's zu erzwingen. // welchen sinn macht dann die decl virtual ~foo()=0; ???? // oder ist das ein bug in meinem compiler (g++) virtual void x(); }; void bar::x() { // das macht sinn ich bin gezwungen die methode bar::x() zu implementieren, // kann aber die implementation von foo::x() verwenden foo::x(); } int main() { bar t; }
-
finix schrieb:
#include <iostream> class Foo { public: virtual void whatever() = 0; }; class Bar : public Foo { public: virtual void whatever(); }; void Foo::whatever() { std::cout << "world!\n"; } void Bar::whatever() { std::cout << "hello\n"; Foo::whatever(); } int main() { Bar test; test.whatever(); }
aber was soll das bringen? das widerspricht ja dem "konzept" von solchen funktionen (func() = 0;) -> sollen eigentlich eine einheitliche schnittstelle darstellen; die eigentlichen implementationen sollen die abgeleiteten klassen "übernehmen"
-
Lars Hupel schrieb:
aber was soll das bringen? das widerspricht ja dem "konzept" von solchen funktionen (func() = 0;) -> sollen eigentlich eine einheitliche schnittstelle darstellen; die eigentlichen implementationen sollen die abgeleiteten klassen "übernehmen"
Nein, es widerspricht nicht.
Denn =0 heisst: abgeleitete Klasse muss es implementieren.
nun kann in Base aber dennoch sinnvolle 'hilfs funktionalität' implementiert sein. zB am beispiel von Java -> die clone Methode.
In C++ könnte man das mit einer rein virtuellen Methode clone() machen. Die abgeleitete Klasse muss clone() definieren aber dennoch Base::clone() aufrufen, weil ja auch Base geklont werden will. So hat man dann in Object eine rein virtuelle clone Methode mit einem Körper.
Da widerspricht sich nichts.