 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Heinz Saathoff Guest
|
Posted: Fri Mar 17, 2006 2:06 pm Post subject: Re: Abstrakte Klasse - Desturktor |
|
|
Moin,
Stefan Reuther schrieb...
| Quote: | Heinz Saathoff wrote:
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.
|
Wenn sie eine Default-Implementierung haben soll, lasse ich das =0 eben
weg. Als jemand, der den Header liest, würde ich nicht unbedingt auf die
Idee kommen, eine als =0 deklarierte Funktion aufzurufen. Im anderen
Fall würde ich mir schon anschauen, welche Defaultimplementation zur
Verfügung gestellt wird.
| Quote: | Das "= 0" lässt zwar den Schluss zu, da würde ein Nullzeiger in die vtbl
geschrieben, aber das ist definitiv nicht der Fall.
|
Wenn eine als =0 deklarierte, aber nirgends definierte Funktion
tatsächlich in der vtbl landen würde, müsste es einen Linkfehler geben.
Gibt's, außer bei Destruktoren, aber nicht. Ein Linkfehler taucht erst
auf, wenn ich eine solche Funktion explizit aufrufe.
| 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).
|
Das habe ich inzwischen auch eingesehen, da ja die Destruktoren von
nichttrivialen Datenmembern auch irgendwie aufgerufen werden müssen. Das
ließe sich zwar vom Compiler auch anders machen, aber so wie's ist,
ist's doch logischer.
| Quote: | 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;
}
|
Wenn Base::foo() nicht implementiert ist, aber aufgerufen wird, meldet
das immerhin noch der Linker. Nur eben etwas neutrale formuliert :-)
- 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 |
|
 |
Stefan Reuther Guest
|
Posted: Fri Mar 17, 2006 7:06 pm Post subject: Re: Abstrakte Klasse - Desturktor |
|
|
Hallo,
Heinz Saathoff wrote:
| Quote: | Stefan Reuther schrieb...
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.
Wenn sie eine Default-Implementierung haben soll, lasse ich das =0 eben
weg.
|
Dann ist aber deine Funktion nicht mehr rein virtuell, und damit zwingst
du den Anwender deiner Klasse nicht mehr dazu, sich Gedanken über die
Implementation der Funktion zu machen.
Und dann gibt's noch sowas wie
class Deletable {
public:
virtual ~Deletable() = 0;
};
inline Deletable::~Deletable() { }
was zweifelsohne abstrakt ist, aber nach weglassen des '=0' es nicht
mehr wäre. Es ist halt einfach anders als Java. Mehr nicht.
| Quote: | 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;
}
:-)
Wenn Base::foo() nicht implementiert ist, aber aufgerufen wird, meldet
das immerhin noch der Linker. Nur eben etwas neutrale formuliert
|
Wie ich gerade sehe, funktioniert das obige doch nicht Es kommt
direkt 'Pure virtual function called'. In der vtbl steht also immer eine
Referenz auf die Funktion, die diesen String ausgibt. Eine rein
virtuelle Funktion mit Rumpf kann man also nur über den qualifizierten
Namen ('Base::foo()') aufrufen.
Laut Standard ist es undefiniert. 10.4p6:
# Member functions can be called from a constructor (or destructor) of
# an abstract class; the effect of making a virtual call (10.3) to a
# pure virtual function directly or indirectly for the object being
# created (or destroyed) from such a constructor (or destructor) is
# undefined.
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 |
|
 |
Powered by phpBB © 2001, 2006 phpBB Group
|