 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Andreas Volz Guest
|
Posted: Tue Mar 14, 2006 4:06 pm Post subject: Abstrakte Klasse - Desturktor |
|
|
Hallo,
Ich habe diese abstrakte Klasse:
class Widget
{
protected:
int positionX;
int positionY;
...
public:
virtual ~Widget () {};
virtual void draw () = 0;
virtual void show () = 0;
virtual void hide () = 0;
...
Es funktioniert so wie gewünscht. Ich verstehe allerdings nicht warum
man einen {}-Teil für den Destruktor angeben muss. Eine rein abstrakte
Klasse kann doch nicht als Objekt angelegt werden. Das ist hier bei
Widget auch erwünscht. Versuche ich den Destruktor "= 0" zu machen,
dann kompiliert der Code zwar, aber die Anwendung die später dagegen
linkt gibt das aus:
undefined reference to `Widget::~Widget [not-in-charge]()'
Kann mir das jemand erklären?
Gruß
Andreas
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
Rolf Magnus Guest
|
Posted: Tue Mar 14, 2006 4:06 pm Post subject: Re: Abstrakte Klasse - Desturktor |
|
|
Andreas Volz wrote:
| Quote: | Hallo,
Ich habe diese abstrakte Klasse:
class Widget
{
protected:
int positionX;
int positionY;
...
public:
virtual ~Widget () {};
virtual void draw () = 0;
virtual void show () = 0;
virtual void hide () = 0;
...
Es funktioniert so wie gewünscht. Ich verstehe allerdings nicht warum
man einen {}-Teil für den Destruktor angeben muss.
|
Weil er sonst nicht definiert ist.
| Quote: | Eine rein abstrakte Klasse kann doch nicht als Objekt angelegt werden.
|
Sie ist aber Teil eines Objekts einer abgeleiteten Klasse. Und bei der
Zerstörung eines Objekts einer abgeleiteten Klasse werden auch die
Destruktoren _aller_ Basisklassen aufgerufen, auch die von abstrakten. Sie
kann ja trotzdem Membervariablen haben, die im Konstruktor initialisiert
und im Destruktor freigegeben werden müssen, genau wie jede andere Klasse.
| Quote: | Das ist hier bei Widget auch erwünscht. Versuche ich den Destruktor "= 0"
zu machen, dann kompiliert der Code zwar, aber die Anwendung die später
dagegen linkt gibt das aus:
undefined reference to `Widget::~Widget [not-in-charge]()'
Kann mir das jemand erklären?
|
Auch ein rein virtueller Destruktorändert nichts daran, daß beim Zerstören
des Objekts der Destruktor der Basisklasse aufgerufen wird. Das "= 0" sorgt
hier lediglich dafür, daß du auch in der abgeleiteten Klasse explizit einen
Desturktor definieren mußt.
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
Heinz Saathoff Guest
|
Posted: Wed Mar 15, 2006 11:06 am Post subject: Re: Abstrakte Klasse - Desturktor |
|
|
Moin,
| Quote: | Eine rein abstrakte Klasse kann doch nicht als Objekt angelegt werden.
Sie ist aber Teil eines Objekts einer abgeleiteten Klasse. Und bei der
Zerstörung eines Objekts einer abgeleiteten Klasse werden auch die
Destruktoren _aller_ Basisklassen aufgerufen, auch die von abstrakten.
|
Das ist zwar so richtig, aber ich habe die Notwendigkeit auch nicht
verstanden. Die Destruktor-Aufrufkette wird ja vom Compiler statisch
generiert. Wenn der Compiler also den Code für den Destruktor einer
abgeleiteten Klasse generiert, dann wird nach der Ausführung des
Destruktors der abgeleiteten Klasse _statisch_ bestimmt, ob der
Destruktor der Basisklasse(n) aufgerufen werden muß (oder bei = 0 eben
nicht). Bei rein virtuellem Destruktor endet dann eben die Aufrufkette
beim ersten Auftreten eines Destruktors==0.
| Quote: | Sie
kann ja trotzdem Membervariablen haben, die im Konstruktor initialisiert
und im Destruktor freigegeben werden müssen, genau wie jede andere Klasse.
|
In dem Fall definiert man halt einen (nicht virtuellen) Destruktor.
BTW(1),
hier könnte ich mir den einzigen Grund für das Vorhandenseinmüssen einer
Definition erklären, nämlich in dem Wunsch, eine abstrakte Basisklasse
mit nur einer einzigen abstrakten Funktion, nämlich dem Destruktor,
definieren zu können, die trotzdem noch 'aufgeräumt' werden kann.
Ansonsten hätte man definieren müssen, daß eine abstrakte Klasse außer
Konstruktoren und dem Destruktor mindestens eine weitere abstrakte
Memberfunktion enthalten muß.
BTW(2),
ich habe gerade mal getestet, ob man auch eine 'normale' abstrakte
Funktion definieren kann. Mein Compiler und mein PC-Lint lassen das zu.
Hätte ich jetzt auch nicht gedacht, daß das erlaubt ist. Zumindest hat
man bei diesen Funktionen die Wahl.
- Heinz
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
Rolf Magnus Guest
|
Posted: Wed Mar 15, 2006 12:06 pm Post subject: Re: Abstrakte Klasse - Desturktor |
|
|
Heinz Saathoff wrote:
| Quote: | Moin,
Eine rein abstrakte Klasse kann doch nicht als Objekt angelegt werden.
Sie ist aber Teil eines Objekts einer abgeleiteten Klasse. Und bei der
Zerstörung eines Objekts einer abgeleiteten Klasse werden auch die
Destruktoren _aller_ Basisklassen aufgerufen, auch die von abstrakten.
Das ist zwar so richtig, aber ich habe die Notwendigkeit auch nicht
verstanden. Die Destruktor-Aufrufkette wird ja vom Compiler statisch
generiert. Wenn der Compiler also den Code für den Destruktor einer
abgeleiteten Klasse generiert, dann wird nach der Ausführung des
Destruktors der abgeleiteten Klasse _statisch_ bestimmt, ob der
Destruktor der Basisklasse(n) aufgerufen werden muß (oder bei = 0 eben
nicht).
|
Nein. Es wird nichts bestimmt. Die Destruktoren aller Basisklassen werden
aufgerufen, ohne Ausnahme. Deshalb muß auch jede Basisklasse einen haben.
| Quote: | Bei rein virtuellem Destruktor endet dann eben die Aufrufkette beim ersten
Auftreten eines Destruktors==0.
|
Nein, sie endet dort nicht. Löse dich mal von virtual und von =0 und von
abstrakten Klassen und all dem, und akzeptiere einfach, daß beim Zerstören
eines Objekts die Destruktoren _aller_ Basisklassen aufgerufen. Das eine
hat mit dem andern nämlich nichts zu tun.
| Quote: | Sie kann ja trotzdem Membervariablen haben, die im Konstruktor
initialisiert und im Destruktor freigegeben werden müssen, genau wie jede
andere Klasse.
In dem Fall definiert man halt einen (nicht virtuellen) Destruktor.
|
Wenn er nicht virtuell ist, kann man das Objekt nicht polymorph zerstören.
| Quote: | BTW(1),
hier könnte ich mir den einzigen Grund für das Vorhandenseinmüssen einer
Definition erklären, nämlich in dem Wunsch, eine abstrakte Basisklasse
mit nur einer einzigen abstrakten Funktion, nämlich dem Destruktor,
definieren zu können, die trotzdem noch 'aufgeräumt' werden kann.
|
Und was, wenn noch mehr rein virtuelle Funktionen da sind? Warum sollte es
dann nicht mehr sinnvoll sein?
| Quote: | Ansonsten hätte man definieren müssen, daß eine abstrakte Klasse außer
Konstruktoren und dem Destruktor mindestens eine weitere abstrakte
Memberfunktion enthalten muß.
BTW(2),
ich habe gerade mal getestet, ob man auch eine 'normale' abstrakte
Funktion definieren kann. Mein Compiler und mein PC-Lint lassen das zu.
Hätte ich jetzt auch nicht gedacht, daß das erlaubt ist. Zumindest hat
man bei diesen Funktionen die Wahl.
|
Da eine überschriebene Funktion in einer abgeleiteten Klasse nicht
automatisch auch die Implementation der Basisklasse aufruft, braucht die
Basisklasse auch keine Implementation. Das ist bei Destruktoren anders.
Es ist durchaus erlaubt, daß eine Funktion rein virtuell ist und eine
Implementation hat. Rein virtuell sagt ja nicht, daß es keine
Implementation gibt, sondern, daß eine abgeleitete Klasse die Funktion
überschreiben muß.
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
kanze Guest
|
Posted: Wed Mar 15, 2006 1:06 pm Post subject: Re: Abstrakte Klasse - Desturktor |
|
|
Heinz Saathoff wrote:
| Quote: | Eine rein abstrakte Klasse kann doch nicht als Objekt
angelegt werden.
Sie ist aber Teil eines Objekts einer abgeleiteten Klasse.
Und bei der Zerstörung eines Objekts einer abgeleiteten
Klasse werden auch die Destruktoren _aller_ Basisklassen
aufgerufen, auch die von abstrakten.
Das ist zwar so richtig, aber ich habe die Notwendigkeit auch
nicht verstanden. Die Destruktor-Aufrufkette wird ja vom
Compiler statisch generiert. Wenn der Compiler also den Code
für den Destruktor einer abgeleiteten Klasse generiert, dann
wird nach der Ausführung des Destruktors der abgeleiteten
Klasse _statisch_ bestimmt, ob der Destruktor der
Basisklasse(n) aufgerufen werden muß (oder bei = 0 eben
nicht). Bei rein virtuellem Destruktor endet dann eben die
Aufrufkette beim ersten Auftreten eines Destruktors==0.
|
Man könnte wohl andere Regeln ausdenken. Die Regel von C++ sind
aber, dass jede Klasse einen Destruktor hat, und dass diesen
Destruktor von den Destruktoren abgeleiteten Klassen aufgerufen
wird. Wenn der Destruktor implizit vom Compiler vereinbart wird,
dann wird auch seine Implementierung vom Compiler gemacht. Wenn
aber du einen Destruktor vereinbarst, auf irgendeinem Grund,
dann musst du auch eine Implementierung zur Verfügung stellen.
Auch: = 0 hinter einer Funktion heißt nicht, dass diese Funktion
keine Implementierung hat. Es heißt 1) dass die Funktion
normalerweise nicht über dynamischen Lookup gefindet wird, und
2) dass die Klasse abstrakt ist, und also nicht instantiert
werden kann. Die Funktion kann, und in bestimmten Fällen (davon
Destruktoren) implementiert werden.
Laut der Sprache, in jedem Fall. Ich finde es durchaus sinnvoll
zu betrachten, dass solche Funktionnen keine Implementierung
haben. Dann aber, dass = 0 auf einem Destruktor verboten ist
(weil er eine Implementierung haben muss). Dass lässt zwar
einiges aus, das die Sprache erlaubt, reicht aber weitgehend aus
für die meisten Fällen.
| Quote: | Sie kann ja trotzdem Membervariablen haben, die im
Konstruktor initialisiert und im Destruktor freigegeben
werden müssen, genau wie jede andere Klasse.
In dem Fall definiert man halt einen (nicht virtuellen)
Destruktor.
BTW(1),
hier könnte ich mir den einzigen Grund für das
Vorhandenseinmüssen einer Definition erklären, nämlich in dem
Wunsch, eine abstrakte Basisklasse mit nur einer einzigen
abstrakten Funktion, nämlich dem Destruktor, definieren zu
können, die trotzdem noch 'aufgeräumt' werden kann. Ansonsten
hätte man definieren müssen, daß eine abstrakte Klasse außer
Konstruktoren und dem Destruktor mindestens eine weitere
abstrakte Memberfunktion enthalten muß.
|
Ich denke, der Hauptgrund ist einfach Orthogonalität. Virtuelle
Funktionnen dürfen rein vereinbart werden; warum soll der
Destructor einen Ausnahme bilden?
| Quote: | BTW(2),
ich habe gerade mal getestet, ob man auch eine 'normale'
abstrakte Funktion definieren kann. Mein Compiler und mein
PC-Lint lassen das zu. Hätte ich jetzt auch nicht gedacht, daß
das erlaubt ist. Zumindest hat man bei diesen Funktionen die
Wahl.
|
Ja und nein. Ruft jemand die abstrakte Funktion auf, dann muss
sie definiert werden. Es ist halt so, dass jemand immer den
Destruktor aufruft.
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
kanze Guest
|
Posted: Wed Mar 15, 2006 2:06 pm Post subject: Re: Abstrakte Klasse - Desturktor |
|
|
Rolf Magnus wrote:
[...]
| Quote: | Es ist durchaus erlaubt, daß eine Funktion rein virtuell ist
und eine Implementation hat. Rein virtuell sagt ja nicht, daß
es keine Implementation gibt, sondern, daß eine abgeleitete
Klasse die Funktion überschreiben muß.
|
Genauer gesagt: um instantiert zu werden muss eine abgeleitete
Klasse alle rein virtuellen Funktionen überschreiben. Was dazu
führt, dass eine rein virtuelle Funktion nie beim dynamischen
Lookup gefunden wird. Außer in Construktoren und Destruktoren,
wo aber es ein undefiniertes Verhalten hat.
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
Heinz Saathoff Guest
|
Posted: Wed Mar 15, 2006 10:06 pm Post subject: Re: Abstrakte Klasse - Desturktor |
|
|
Moin,
| Quote: | Das ist zwar so richtig, aber ich habe die Notwendigkeit auch
nicht verstanden. Die Destruktor-Aufrufkette wird ja vom
Compiler statisch generiert. Wenn der Compiler also den Code
für den Destruktor einer abgeleiteten Klasse generiert, dann
wird nach der Ausführung des Destruktors der abgeleiteten
Klasse _statisch_ bestimmt, ob der Destruktor der
Basisklasse(n) aufgerufen werden muß (oder bei = 0 eben
nicht). Bei rein virtuellem Destruktor endet dann eben die
Aufrufkette beim ersten Auftreten eines Destruktors==0.
Man könnte wohl andere Regeln ausdenken.
|
Das ist es, was ich auch anmerken wollte.
| Quote: | Die Regel von C++ sind
aber, dass jede Klasse einen Destruktor hat, und dass diesen
Destruktor von den Destruktoren abgeleiteten Klassen aufgerufen
wird.
|
So ist es eben aktuell festgelegt.
| Quote: | Wenn der Destruktor implizit vom Compiler vereinbart wird,
dann wird auch seine Implementierung vom Compiler gemacht.
|
Na ja, aus der Sicht des Standards vielleicht, aber in Realität wird ein
solcher 'impliziter Destruktor' gar nicht aufgerufen (wen man sich den
Code anschaut). Der Compiler wiß in diesem Fall, daß der Programmierer
keinen Destruktor deklariert hat, also nichts wirkliches zu tun ist,
also braucht er keinen Code erzeugen.
Das ist im Prinzip nichts anderes, als was ich auch bei einem abstrakten
virtuellen Destruktor erwarten würde.
| Quote: | Wenn
aber du einen Destruktor vereinbarst, auf irgendeinem Grund,
dann musst du auch eine Implementierung zur Verfügung stellen.
|
Weil es eben so festgelegt ist.
| Quote: | Auch: = 0 hinter einer Funktion heißt nicht, dass diese Funktion
keine Implementierung hat. Es heißt 1) dass die Funktion
normalerweise nicht über dynamischen Lookup gefindet wird, und
2) dass die Klasse abstrakt ist, und also nicht instantiert
werden kann. Die Funktion kann, und in bestimmten Fällen (davon
Destruktoren) implementiert werden.
|
Soweit ist es eben momentan festgeschrieben. Nur muß das unbedingt so
festgeschrieben sein? Hätte man nicht sagen können, daß alle virtuellen
Memberfunktionen= 0 nicht implementiert werden können/dürfen?
| Quote: | Laut der Sprache, in jedem Fall. Ich finde es durchaus sinnvoll
zu betrachten, dass solche Funktionnen keine Implementierung
haben.
|
Du stimmst mir also zu ;-)
| Quote: | Dann aber, dass = 0 auf einem Destruktor verboten ist
(weil er eine Implementierung haben muss).
|
Oder man trennt sich vom 'Compiler generierten Destruktor' im Fall des
nicht explizit deklarierten und implementierten Destruktors. Damit
könnte man definieren, daß im Fall eines nicht vorhandenen Destruktors
für so eine Klasse keine Bereinigungen durchgeführt werden und dies auch
für virtuele abstrakte Destruktoren gilt.
| Quote: | Dass lässt zwar
einiges aus, das die Sprache erlaubt, reicht aber weitgehend aus
für die meisten Fällen.
|
Ich kann ja auch mit der derzeitigen Situation leben. Nur scheint sie
mir nicht ganz konsequent.
| Quote: | BTW(2),
ich habe gerade mal getestet, ob man auch eine 'normale'
abstrakte Funktion definieren kann. Mein Compiler und mein
PC-Lint lassen das zu. Hätte ich jetzt auch nicht gedacht, daß
das erlaubt ist. Zumindest hat man bei diesen Funktionen die
Wahl.
Ja und nein. Ruft jemand die abstrakte Funktion auf, dann muss
sie definiert werden. Es ist halt so, dass jemand immer den
Destruktor aufruft.
|
Da der Compiler das erkennen kann, könnte er einen Fehler ausgeben. Beim
Destruktor als Spezielfall würde er selber die Aufufkette beenden. Wenn
der Programmierer also sowas schreibt:
struct Base {
// ...
virtual void Foo() = 0;
};
struct Derived : public Base {
// ...
virtual void Foo() {
// ...
Base::Foo();
^^^^^^^^^^^^^^^
C++ Compiler XYZ, Error: Base::Foo is a abstract function that as no
implementation and can not be called!
Irgendwas in dieser Art.
- Heinz
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
Heinz Saathoff Guest
|
Posted: Wed Mar 15, 2006 10:06 pm Post subject: Re: Abstrakte Klasse - Desturktor |
|
|
Moin,
| Quote: | Das ist zwar so richtig, aber ich habe die Notwendigkeit auch nicht
verstanden. Die Destruktor-Aufrufkette wird ja vom Compiler statisch
generiert. Wenn der Compiler also den Code für den Destruktor einer
abgeleiteten Klasse generiert, dann wird nach der Ausführung des
Destruktors der abgeleiteten Klasse _statisch_ bestimmt, ob der
Destruktor der Basisklasse(n) aufgerufen werden muß (oder bei = 0 eben
nicht).
Nein. Es wird nichts bestimmt. Die Destruktoren aller Basisklassen werden
aufgerufen, ohne Ausnahme. Deshalb muß auch jede Basisklasse einen haben.
|
Ja, so will es der derzeitige Standard. Was ich sagen wollte ist, daß es
auch anders ginge. Implementationstechnisch besteht IMO kein zwingender
Grund, daß es so zu machen ist, wie's im Moment durch den Standard
vorgeschrieben wird. Und von der Logik her sehe ich auch keinen Grund.
| Quote: | Bei rein virtuellem Destruktor endet dann eben die Aufrufkette beim ersten
Auftreten eines Destruktors==0.
Nein, sie endet dort nicht. Löse dich mal von virtual und von =0 und von
abstrakten Klassen und all dem, und akzeptiere einfach, daß beim Zerstören
eines Objekts die Destruktoren _aller_ Basisklassen aufgerufen. Das eine
hat mit dem andern nämlich nichts zu tun.
Sie kann ja trotzdem Membervariablen haben, die im Konstruktor
initialisiert und im Destruktor freigegeben werden müssen, genau wie jede
andere Klasse.
In dem Fall definiert man halt einen (nicht virtuellen) Destruktor.
Wenn er nicht virtuell ist, kann man das Objekt nicht polymorph zerstören.
|
Ich meinte eigentlich 'nicht abstrakten Destruktor'.
Also, was spräche gegen eine hypothetische Version des Standards, die
festlegt, daß
- ein abstakt virtueller Destruktor nicht implementiert wird
- ein nicht abstrakter Destruktor definiert werden kann, aber
damit die Klasse nur dann noch abstrakt ist, wenn mindestens
eine weitere Memberfunktion abstrakt deklariert ist.
| Quote: | BTW(1),
hier könnte ich mir den einzigen Grund für das Vorhandenseinmüssen einer
Definition erklären, nämlich in dem Wunsch, eine abstrakte Basisklasse
mit nur einer einzigen abstrakten Funktion, nämlich dem Destruktor,
definieren zu können, die trotzdem noch 'aufgeräumt' werden kann.
Und was, wenn noch mehr rein virtuelle Funktionen da sind? Warum sollte es
dann nicht mehr sinnvoll sein?
|
Es könnte auch dann noch sinnvoll sein, nämlich wenn die Klasse
als reine Interfaceklasse keine Aufräumarbeiten benötigt.
Also, ~Base()=0 => keine Funktionsdefinition notwendig (sogar nicht
erlaubt), ~Base(); => es muß eine Funktionsdefinition existieren.
Ich fände diese Regel logischer als die vom Standard geforderte.
Ich finde es auch nicht besonders logisch, daß dies erlaubt ist:
class Base {
//...
virtual void Foo() = 0;
};
class Derived : public Base {
//...
virtual void Foo() {
// ...
Base::Foo(); // erlaubt! Aber sinnvoll?
}
};
Warum sollte man Base::Foo() aus der Derived-Klasse aufrufen wollen,
wenn diese doch als reines Interface deklariert ist.
| Quote: | BTW(2),
ich habe gerade mal getestet, ob man auch eine 'normale' abstrakte
Funktion definieren kann. Mein Compiler und mein PC-Lint lassen das zu.
Hätte ich jetzt auch nicht gedacht, daß das erlaubt ist. Zumindest hat
man bei diesen Funktionen die Wahl.
Da eine überschriebene Funktion in einer abgeleiteten Klasse nicht
automatisch auch die Implementation der Basisklasse aufruft, braucht die
Basisklasse auch keine Implementation.
|
Aber man kann sie expilit aufrufen. Zumindest läßt es mein Compiler und
PC-Lint zu. Beim Linken gibt's dann genauso den Fehler wie beim
Destruktor.
| Quote: | Es ist durchaus erlaubt, daß eine Funktion rein virtuell ist und eine
Implementation hat. Rein virtuell sagt ja nicht, daß es keine
Implementation gibt, sondern, daß eine abgeleitete Klasse die Funktion
überschreiben muß.
|
Gut, so ist es halt im Standard festgelegt worden. Ich hätte es für mich
nur logischer empfunden, wenn 'virtual func() = 0;' bedeuten würde, daß
es keine Implementierung von func() gibt (und auch nicht geben darf),
und das dies auch für Destruktoren gelten würde.
- Heinz
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
Rolf Magnus Guest
|
Posted: Thu Mar 16, 2006 2:06 am Post subject: Re: Abstrakte Klasse - Desturktor |
|
|
Heinz Saathoff wrote:
| Quote: | Moin,
Das ist zwar so richtig, aber ich habe die Notwendigkeit auch nicht
verstanden. Die Destruktor-Aufrufkette wird ja vom Compiler statisch
generiert. Wenn der Compiler also den Code für den Destruktor einer
abgeleiteten Klasse generiert, dann wird nach der Ausführung des
Destruktors der abgeleiteten Klasse _statisch_ bestimmt, ob der
Destruktor der Basisklasse(n) aufgerufen werden muß (oder bei = 0 eben
nicht).
Nein. Es wird nichts bestimmt. Die Destruktoren aller Basisklassen werden
aufgerufen, ohne Ausnahme. Deshalb muß auch jede Basisklasse einen haben.
Ja, so will es der derzeitige Standard. Was ich sagen wollte ist, daß es
auch anders ginge. Implementationstechnisch besteht IMO kein zwingender
Grund, daß es so zu machen ist, wie's im Moment durch den Standard
vorgeschrieben wird. Und von der Logik her sehe ich auch keinen Grund.
|
Was du willst, wäre halt eine zusätzliche Sonderregel, die eigentlich keinen
wirklichen Vorteil bringt.
| Quote: | Also, was spräche gegen eine hypothetische Version des Standards, die
festlegt, daß
- ein abstakt virtueller Destruktor nicht implementiert wird
- ein nicht abstrakter Destruktor definiert werden kann, aber
damit die Klasse nur dann noch abstrakt ist, wenn mindestens
eine weitere Memberfunktion abstrakt deklariert ist.
|
Siehe unten.
| Quote: | BTW(1),
hier könnte ich mir den einzigen Grund für das Vorhandenseinmüssen
einer Definition erklären, nämlich in dem Wunsch, eine abstrakte
Basisklasse mit nur einer einzigen abstrakten Funktion, nämlich dem
Destruktor, definieren zu können, die trotzdem noch 'aufgeräumt' werden
kann.
Und was, wenn noch mehr rein virtuelle Funktionen da sind? Warum sollte
es dann nicht mehr sinnvoll sein?
Es könnte auch dann noch sinnvoll sein, nämlich wenn die Klasse
als reine Interfaceklasse keine Aufräumarbeiten benötigt.
Also, ~Base()=0 => keine Funktionsdefinition notwendig (sogar nicht
erlaubt), ~Base(); => es muß eine Funktionsdefinition existieren.
Ich fände diese Regel logischer als die vom Standard geforderte.
Ich finde es auch nicht besonders logisch, daß dies erlaubt ist:
class Base {
//...
virtual void Foo() = 0;
};
class Derived : public Base {
//...
virtual void Foo() {
// ...
Base::Foo(); // erlaubt! Aber sinnvoll?
}
};
Warum sollte man Base::Foo() aus der Derived-Klasse aufrufen wollen,
wenn diese doch als reines Interface deklariert ist.
|
Weil dort evtl. eine Default-Implementation enthalten ist, die von vielen
abgeleiteten Klassen verwendet werden kann. Wenn ich jetzt noch will, daß
derjenige, der ableitet, sich trotzdem auf jeden Fall um Foo kümmern muß,
mache ich diese Funktion rein virtuell. Mag ein eher selten genutztes
Feature sein, aber eine zusätliche Regel einzuführen, nur damit das nicht
mehr geht, ist meines Erachtens wenig sinnvoll.
| Quote: | BTW(2),
ich habe gerade mal getestet, ob man auch eine 'normale' abstrakte
Funktion definieren kann. Mein Compiler und mein PC-Lint lassen das zu.
Hätte ich jetzt auch nicht gedacht, daß das erlaubt ist. Zumindest hat
man bei diesen Funktionen die Wahl.
Da eine überschriebene Funktion in einer abgeleiteten Klasse nicht
automatisch auch die Implementation der Basisklasse aufruft, braucht die
Basisklasse auch keine Implementation.
Aber man kann sie expilit aufrufen. Zumindest läßt es mein Compiler und
PC-Lint zu. Beim Linken gibt's dann genauso den Fehler wie beim
Destruktor.
|
Ja. Und wenn du aber genau das willst, also daß die abgeleitete Klasse die
Funktion überschreiben muß, aber dort die Implementation der Basisklasse
aufrufen kann, dafür gibt's die Möglichkeit, einer rein virtuellen Funktion
eine Implementation mitzugeben.
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
Kurt Stege Guest
|
Posted: Thu Mar 16, 2006 11:06 am Post subject: Re: Abstrakte Klasse - Desturktor |
|
|
Heinz Saathoff wrote:
<Es geht um den Aufruf eines als abstrakt deklarierten Destruktors.>
| Quote: | Ja, so will es der derzeitige Standard. Was ich sagen wollte ist, daß es
auch anders ginge. Implementationstechnisch besteht IMO kein zwingender
Grund, daß es so zu machen ist, wie's im Moment durch den Standard
vorgeschrieben wird. Und von der Logik her sehe ich auch keinen Grund.
|
Du hast eine andere Vorstellung von "=0" als ich.
Laut Standard ist eine Klasse abstrakt, wenn sie mindestens eine
"pure virtual function" hat. Die Bedeutung von "abstrakt" ist,
daß die Klasse nicht instanziiert werden kann.
Das "=0" ist ein "pure specifier", der eine virtuelle Funktion
"pure virtual" macht. Die Semantik ist nicht, "diese Funktion
ist nicht implementiert und darf nicht aufgerufen werden",
sondern "diese Klasse ist abstrakt, und solange abgeleitete
Klassen nicht den pure specifier für diese Funktion entfernen,
bleiben sie es auch".
Der pure specifier hat deshalb nichts damit zu tun, ob die
Funktion implementiert ist oder nicht. Normale member functions
kannst Du ja auch deklarieren und anschließend die Implementierung
vergessen; dann kann man die Funktionen auch nicht aufrufen.
Das macht man ja gerne mit dem privaten Default-Konstruktor so...
(Ich weiß gerade gar nicht, ob eine Deklaration, zu der es keine
einzige Definition gibt, vom Standard überhaupt zugelassen ist,
oder ob es z.B. gegen die one-definition-rule verstößt. Für den
Fall "pure specifier" ist es ausdrücklich in 10.4(2).)
Und von dieser Logik her sehe ich keinen Grund, etwas zu ändern.
| Quote: | Ich meinte eigentlich 'nicht abstrakten Destruktor'.
Also, was spräche gegen eine hypothetische Version des Standards, die
festlegt, daß
- ein abstakt virtueller Destruktor nicht implementiert wird
- ein nicht abstrakter Destruktor definiert werden kann, aber
damit die Klasse nur dann noch abstrakt ist, wenn mindestens
eine weitere Memberfunktion abstrakt deklariert ist.
|
Er schränkt ein. Von vier Fällen für eine Funktion läßt Du nur
noch zwei zu, nämlich "pure + non-implemented" und "non-pure +
implemented". Die Fälle "pure + implemented" und "non-pure +
non-implemented" fallen unötigerweise unter dem Tisch.
OK. Obiger Satz gilt so, wenn Du Deine Regelung für alle
Funktionen gelten lassen würdest. Speziell beim Destruktor
eine Sonderbehandlung einzuführen, scheint mir umständlich
zu sein.
Da der Destruktor ja immer aufgerufen wird, muß er auch immer
implementiert sein. Deshalb bleiben hier nur noch zwei
Möglichkeiten übrig, die sich linken lassen: "pure + implemented"
und "non-pure + implemented".
Du willst mit Deiner Regel "pure + implemented" verbieten
und dafür "pure + non-implemented" ermöglichen. Das erste
ist wieder eine unnötige Einschränkung, und das zweite ist
(für mich) nicht nötig, weil ich keinen praktischen Unterschied
sehe zwischen einen non-implemented Destruktor, der nicht
aufgerufen wird, weil der Compiler schon weiß, daß er fehlt,
und einen implementierten lleren Destruktur, der formal
aufgerufen wird aber praktisch wiederum nicht, weil der
Compiler bereits weiß, daß er leer ist.
Bleibt dann noch die Frage: Weshalb willst Du den Destruktor
"pure" machen?
| Quote: | Also, ~Base()=0 => keine Funktionsdefinition notwendig (sogar nicht
erlaubt), ~Base(); => es muß eine Funktionsdefinition existieren.
Ich fände diese Regel logischer als die vom Standard geforderte.
|
Das liegt einfach daran, (das ist nicht bewertend von mir gemeint)
daß Du eine andere Logik verfolgst als der Standard.
| Quote: | Ich finde es auch nicht besonders logisch, daß dies erlaubt ist:
class Base {
//...
virtual void Foo() = 0;
};
class Derived : public Base {
//...
virtual void Foo() {
// ...
Base::Foo(); // erlaubt! Aber sinnvoll?
}
};
Warum sollte man Base::Foo() aus der Derived-Klasse aufrufen wollen,
wenn diese doch als reines Interface deklariert ist.
|
Aus den gleichen Gründen aus denen auch normale abgeleitete
Funktionen die Implementierung der Basisklasse nutzen wollen.
Das "= 0" ändert nichts daran, wie eine Funktion zu verwenden
ist.
| Quote: | Da eine überschriebene Funktion in einer abgeleiteten Klasse nicht
automatisch auch die Implementation der Basisklasse aufruft, braucht die
Basisklasse auch keine Implementation.
Aber man kann sie expilit aufrufen. Zumindest läßt es mein Compiler und
PC-Lint zu. Beim Linken gibt's dann genauso den Fehler wie beim
Destruktor.
|
Ja klar. Immer dann, wenn Du Funktionen verwendest, die deklariert aber
nicht implementiert sind, gibt es einen Linker-Fehler sobald diese
Funktionen aufgerufen werden sollen.
| Quote: | Gut, so ist es halt im Standard festgelegt worden. Ich hätte es für mich
nur logischer empfunden, wenn 'virtual func() = 0;' bedeuten würde, daß
es keine Implementierung von func() gibt (und auch nicht geben darf),
und das dies auch für Destruktoren gelten würde.
|
Der Standard hat aber festgelegt, daß das "= 0" die Funktion als "pure"
deklariert, welches einzig und allein die Wirkung hat, daß die Klasse,
die diese Funktion enthält, abstrakt ist. Mehr nicht. Ob es für die
Funktion eine Implementierung gibt oder nicht, braucht das Header-File,
das die Klasse definiert, gar nicht zu wissen.
Gruß,
Kurt.
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
Tibor Pausz Guest
|
Posted: Thu Mar 16, 2006 11:06 am Post subject: Re: Abstrakte Klasse - Desturktor |
|
|
Heinz Saathoff <hsaat (AT) despammed (DOT) com> wrote:
| Quote: | Nur muß das unbedingt so festgeschrieben sein?
|
Ja, anderfalls bekommt man Probleme beim Design.
Ein Beispiel
class Basis {
char const* const p_;
public:
Basis (char const* const s);
virtual ~Basis () = 0;
};
Diese Basisklasse definiert, daß alle abgeleiteten Klassen eine internen
Zeiger auf eine Zeichenkette vorhalten und die Objekte diesen
Zeichenketten auch verwalten müssen, dann ist ein Destruktor notwendig.
Allerdings sollen von Basis keine Objekte existieren können.
Momentan ist das möglich, mit der von Dir vorgeschlagenen Änderung nicht
mehr.
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
kanze Guest
|
Posted: Thu Mar 16, 2006 4:06 pm Post subject: Re: Abstrakte Klasse - Desturktor |
|
|
Heinz Saathoff wrote:
| Quote: | Das ist zwar so richtig, aber ich habe die Notwendigkeit
auch nicht verstanden. Die Destruktor-Aufrufkette wird ja
vom Compiler statisch generiert. Wenn der Compiler also
den Code für den Destruktor einer abgeleiteten Klasse
generiert, dann wird nach der Ausführung des Destruktors
der abgeleiteten Klasse _statisch_ bestimmt, ob der
Destruktor der Basisklasse(n) aufgerufen werden muß (oder
bei = 0 eben nicht). Bei rein virtuellem Destruktor endet
dann eben die Aufrufkette beim ersten Auftreten eines
Destruktors==0.
Man könnte wohl andere Regeln ausdenken.
Das ist es, was ich auch anmerken wollte.
|
Sicher. Die Regeln sind aber nicht ohne Grunde.
| Quote: | Die Regel von C++ sind aber, dass jede Klasse einen
Destruktor hat, und dass diesen Destruktor von den
Destruktoren abgeleiteten Klassen aufgerufen wird.
So ist es eben aktuell festgelegt.
Wenn der Destruktor implizit vom Compiler vereinbart wird,
dann wird auch seine Implementierung vom Compiler gemacht.
Na ja, aus der Sicht des Standards vielleicht, aber in
Realität wird ein solcher 'impliziter Destruktor' gar nicht
aufgerufen (wen man sich den Code anschaut).
|
Doch. Ich vermute, dass er bei den meisten Compilern genau
gehandelt wird, als ob du einen inline, leeren Destructor
definiert hast. Du gehst von einem bestimmten Basisklasse aus,
wo er nicht zu tun hat. Das ist aber nicht immer der Fall. Auch
implizierte Destruktore müssen die Destruktore Basisklassen und
Mitglieder aufrufen. In bestimmten Fällen muss er auch den vptr
ändern. (In Prinzip immer. In den meisten Fällen aber kann der
Compiler festlegen, dass den neuen vptr sowieso nicht benutzt
wird.)
| Quote: | Der Compiler wiß in diesem Fall, daß der Programmierer keinen
Destruktor deklariert hat, also nichts wirkliches zu tun ist,
also braucht er keinen Code erzeugen. Das ist im Prinzip
nichts anderes, als was ich auch bei einem abstrakten
virtuellen Destruktor erwarten würde.
|
Im ersten Fall weiss der Compiler, daß es nichts zu tun ist, nur
weil er die Implementierung des Destructors sieht. Genauso als
wenn der Programmierer den Destructor inline geschrieben hat.
| Quote: | Wenn aber du einen Destruktor vereinbarst, auf irgendeinem
Grund, dann musst du auch eine Implementierung zur Verfügung
stellen.
Weil es eben so festgelegt ist.
|
Und wie willst du es anders haben: A priori, DU kannst nicht
entscheiden, ob der Destruktor echt leer ist oder nicht. Oder
mindestens wills du es nicht; am sonsten musst du immer an die
Regeln denken, wenn ein Destruktor »trivial« ist, und wenn
nicht. Und ob der Destruktor trivial ist oder nicht hängt von
den Destruktoren Basisklassen und Datenmitgliedern ab. Worüber
du als Benutzer nicht zu wissen hast.
Mann könnte freilich die Regel haben, dass wenn du = 0 hinter
den Destruktor schreibst, heißt es, dass der Compiler soll ihn
generieren -- m.E. wäre das nicht unbedingt eine schlechte
Regel: es würde es erlauben, dass du den Destruktor virtual oder
proctected machst, ohen ihn zu implementieren. Es wäre aber noch
ein Sonderfall, weil das nicht die Bedeutung von = 0 ist bei
anderen Funktionen. (Man könnte es aber erweitern auf andere
»impliziten« Funktionen.)
| Quote: | Auch: = 0 hinter einer Funktion heißt nicht, dass diese
Funktion keine Implementierung hat. Es heißt 1) dass die
Funktion normalerweise nicht über dynamischen Lookup
gefindet wird, und 2) dass die Klasse abstrakt ist, und also
nicht instantiert werden kann. Die Funktion kann, und in
bestimmten Fällen (davon Destruktoren) implementiert werden.
Soweit ist es eben momentan festgeschrieben. Nur muß das
unbedingt so festgeschrieben sein? Hätte man nicht sagen
können, daß alle virtuellen Memberfunktionen= 0 nicht
implementiert werden können/dürfen?
Laut der Sprache, in jedem Fall. Ich finde es durchaus
sinnvoll zu betrachten, dass solche Funktionen keine
Implementierung haben.
Du stimmst mir also zu
|
Jain. Wenn man nur auf den gängigen Benutzungen denkt, kann man
es so betrachten. In der Tat tue ich es auch, einfachshalber.
Dann aber benutze ich nie einen rein virtuellen Destructor.
| Quote: | Dann aber, dass = 0 auf einem Destruktor verboten ist (weil
er eine Implementierung haben muss).
Oder man trennt sich vom 'Compiler generierten Destruktor' im
Fall des nicht explizit deklarierten und implementierten
Destruktors.
|
Aber dann hat man einen Sonderfall. = 0 bedeutet etwas anders,
wenn es auf einen Destruktor vorkommt. Das ist auch nicht
besonders wünschenswert.
| Quote: | Damit könnte man definieren, daß im Fall eines nicht
vorhandenen Destruktors für so eine Klasse keine Bereinigungen
durchgeführt werden und dies auch für virtuele abstrakte
Destruktoren gilt.
|
Das kann man in keinem Fall. Wenn Bereinigung gibt, dann muss es
unbedingt durchgeführt werden.
Stell dich vor: du hast einen rein virtuellen Destruktor
eingesetzt, weil du weißt, dass es nichts zu bereinigen gibt.
Später, in der Wartung, fügt man einen std::string als Mitglied
zu -- sagen wir, dass die Objekte müssen neulich einen Namen
haben. Bist du sicher, dass er auch daran denkt, deine rein
virtuell zu entfernen, und der Destruktor zu implementieren?
| Quote: | Dass lässt zwar einiges aus, das die Sprache erlaubt, reicht
aber weitgehend aus für die meisten Fällen.
Ich kann ja auch mit der derzeitigen Situation leben. Nur
scheint sie mir nicht ganz konsequent.
|
Wenn man die formelle Sprachdefinition betrachtet, find ich sie
sehr konsequent. Wenn man die lockere Ansicht nimmt, dann hat
man auch keine rein virtuellen Destructore, und es kommt auf
dasselbe.
| Quote: | BTW(2),
ich habe gerade mal getestet, ob man auch eine 'normale'
abstrakte Funktion definieren kann. Mein Compiler und mein
PC-Lint lassen das zu. Hätte ich jetzt auch nicht gedacht,
daß das erlaubt ist. Zumindest hat man bei diesen
Funktionen die Wahl.
Ja und nein. Ruft jemand die abstrakte Funktion auf, dann
muss sie definiert werden. Es ist halt so, dass jemand immer
den Destruktor aufruft.
Da der Compiler das erkennen kann, könnte er einen Fehler
ausgeben. Beim Destruktor als Spezielfall würde er selber die
Aufufkette beenden. Wenn der Programmierer also sowas
schreibt:
struct Base {
// ...
virtual void Foo() = 0;
};
struct Derived : public Base {
// ...
virtual void Foo() {
// ...
Base::Foo();
^^^^^^^^^^^^^^^
C++ Compiler XYZ, Error: Base::Foo is a abstract function that
as no implementation and can not be called!
|
Das macht in normallem Fall der Linker.
In der Tat könnte man Implementierungen von rein virtuellen
Funktionnen verbieten. Ich bin auch der Meinung, dass die
relativ wenig Sinn haben. Dann könnte der Compiler den Fehler
generieren. Dann wäre aber auch konsequenterweise rein
virtuelle Destruktore verboten, weil ein Destruktor muss eine
Implementierung haben. Eine dritte Lösung wäre es, dass wenn =
0 hinter einer »implizierten« Funktion steht, heißt es, dass der
Compiler um die Implementierung kummern soll, obwohl die
Funktion explizit vereinbart wurde.
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
Stefan Reuther Guest
|
Posted: Thu Mar 16, 2006 6:06 pm Post subject: Re: Abstrakte Klasse - Desturktor |
|
|
Hallo,
Heinz Saathoff wrote:
| Quote: | Ich finde es auch nicht besonders logisch, daß dies erlaubt ist:
class Base {
//...
virtual void Foo() = 0;
};
class Derived : public Base {
//...
virtual void Foo() {
// ...
Base::Foo(); // erlaubt! Aber sinnvoll?
}
};
Warum sollte man Base::Foo() aus der Derived-Klasse aufrufen wollen,
wenn diese doch als reines Interface deklariert ist.
|
Dein Denkfehler liegt vermutlich einfach darin, dass du Interfaces mit
abstrakten Klassen gleichsetzt. Das ist aber einfach nicht so. Eine
abstrakte Klasse kann mehr als ein Interface, sie kann nämlich
Default-Implementationen für die Funktionen zur Verfügung stellen.
Das "= 0" lässt zwar den Schluss zu, da würde ein Nullzeiger in die vtbl
geschrieben, aber das ist definitiv nicht der Fall.
| Quote: | Gut, so ist es halt im Standard festgelegt worden. Ich hätte es für mich
nur logischer empfunden, wenn 'virtual func() = 0;' bedeuten würde, daß
es keine Implementierung von func() gibt (und auch nicht geben darf),
und das dies auch für Destruktoren gelten würde.
|
Da ist zum einen das Problem, dass es keine Klasse ohne Destruktor geben
kann (und wenn's ein compilergenerierter ist, der nichts tut).
Zum anderen ist es in C++ bekanntermaßen so, das Objekte nicht direkt
mit dem richtigen Typ geboren werden (wie z.B. in Turbo Pascal), sondern
als Basisklassenobjekt entstehen und dann während der Subklassen-
konstruktoren zu einem most-derived-object heranwachsen. So ein Sub-
klassenkonstruktor kann eben auch virtuelle Methoden aufrufen, und
bekommt dann eben die der aktuellen Klasse, nicht die des most-derived-
object-Typs. Und da wäre doch mal ein nützlicher Anwendungsfall für eine
abstrakte implementierte Methode:
class Base {
public:
virtual void foo() = 0;
};
void Base::foo() {
std::cout << "Du Depp hast aus dem Konstruktor eine virtuelle "
"Methode aufgerufen!!!!!!!!!1" << std::endl;
}
:-)
Stefan
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
Stefan Reuther Guest
|
Posted: Thu Mar 16, 2006 6:06 pm Post subject: Re: Abstrakte Klasse - Desturktor |
|
|
Kurt Stege wrote:
| Quote: | (Ich weiß gerade gar nicht, ob eine Deklaration, zu der es keine
einzige Definition gibt, vom Standard überhaupt zugelassen ist,
oder ob es z.B. gegen die one-definition-rule verstößt.
|
Ist es. Die ODR fordert eine Definition für jede benutzte Funktion. Ergo
müssen unbenutzte Funktionen auch nicht definiert werden. Als benutzt
gelten alle irgendwie referenzierten Funktionen sowie alle virtuellen
Funktionen.
Stefan
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
Heinz Saathoff Guest
|
Posted: Fri Mar 17, 2006 12:51 pm Post subject: Re: Abstrakte Klasse - Desturktor |
|
|
Moin,
kanze schrieb...
| Quote: | Man könnte wohl andere Regeln ausdenken.
Das ist es, was ich auch anmerken wollte.
Sicher. Die Regeln sind aber nicht ohne Grunde.
|
Ich glaube, ich habe jetzt den Grund erkannt. Mit Deinem folgenden
Beispiel hast Du mir die Augen geöffnet:
| Quote: | Damit könnte man definieren, daß im Fall eines nicht
vorhandenen Destruktors für so eine Klasse keine Bereinigungen
durchgeführt werden und dies auch für virtuele abstrakte
Destruktoren gilt.
Das kann man in keinem Fall. Wenn Bereinigung gibt, dann muss es
unbedingt durchgeführt werden.
Stell dich vor: du hast einen rein virtuellen Destruktor
eingesetzt, weil du weißt, dass es nichts zu bereinigen gibt.
Später, in der Wartung, fügt man einen std::string als Mitglied
zu -- sagen wir, dass die Objekte müssen neulich einen Namen
haben. Bist du sicher, dass er auch daran denkt, deine rein
virtuell zu entfernen, und der Destruktor zu implementieren?
|
Da die abstrakte Basisklasse nicht nur einfache Daten wie char, int
enthalten kann, sondern auch Datenobjekte, die selber einen Destruktor
haben (z.B. Container der Standard-Lib), muß sichergestellt werden, daß
deren Destruktoren ausgeführt werden. Wenn man jetzt festlegen würde,
daß ~Base()=0 nicht implementiert wird, müsste der Compiler trotzdem, wi
im Falle eines nicht vorhandenen Destruktors, Code zum Aufruf der
Destruktoren der Datenobjekte generieren.
So gesehen ist die Regel, daß ein vom Programmierer deklarierter
Destruktor auch immer implementiert werden muß, wieder sinnvoll.
- Heinz
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
Powered by phpBB © 2001, 2006 phpBB Group
|