Article View: de.comp.lang.c++
Article #591Re: Wiedermal: Virtuelle Methoden
From: Karl-Heinz Krause
Date: Mon, 16 Oct 1995 19:36
Date: Mon, 16 Oct 1995 19:36
96 lines
3573 bytes
3573 bytes
Am 15. Okt 1995 schrieb Roman Bartke (rob@robot.mayn.de):
> Meine lieben VIRTUosen!
> Gegeben sei folgender Programmrumpf, bei dem das Verhalten der
> ShowError-Methode des Clients durch Vererbung modifiziert werden soll.
> Das Connect() simuliert hierzu immer einen Fehler.
> c.cc:
> ------------------------------------------------------------------------
> #include <iostream.h>
> class Client
> {
> public:
> Client() { Connect(); }
> virtual ~Client() { }
> void Connect() { ShowError(); }
> protected:
> virtual void ShowError() { cerr << "Client::ShowError()\n"; }
> };
> class SpecialClient : public Client
> {
> public:
> SpecialClient():Client() { }
> protected:
> void ShowError() { cerr << "SpecialClient::ShowError()\n"; }
> };
> int main(int argc, char *argv[])
> {
> SpecialClient client;
> client.Connect();
> return 0;
> }
> ------------------------------------------------------------------------
> "g++ -Wall -o c c.cc -lg++; c" liefert:
> Client::ShowError()
> SpecialClient::ShowError()
> Ich hätte hier
> SpecialClient::ShowError()
> SpecialClient::ShowError()
> erwartet, da es beidemale um einen SpecialClient ging.
> Warum ruft der Konstruktor nicht die neue virtuelle Methode auf,
> sondern noch die alte?
Das hängt mit der Art zusammen, wie C++ Objekte initialisiert. Jedes
SpecialClient-Objekt enthält ein Client-Objekt. Wird ein SpecialClinent-
Objekt erzeugt, so wird zuerst das Client-Objekt initialisiert, durch
Aufruf des Konstruktors Client(). Zu diesem Zeitpunkt sind die
virtuellen Funktionen noch nicht überschrieben, d. h. wenn der
Konstruktor Client() direkt oder indirekt ShowError aufruft, so benutzt
er Client::ShowError.
Erst nach der Initialisierung des Client-Objekts werden die Funktionen
überschrieben und dann der Konstruktorcode von SpecialClient()
aufgerufen.
Ein Ausweg wäre, Initialisierungscode, der von virtuellen Funktionen
abhängt, nicht in den Konstruktor hineinzuschreiben, sondern in eine
spezielle Init-Methode, die dann aber nicht vom Konstruktor aufgerufen
werden darf, sondern getrennt aufgerufen werden muß.
> Das ist im Beispiel tragisch, da der Konstruktor bei neudefinierten
> virtuellen Methoden nicht automatisch "connecten" darf...
Wenn es allein darum geht, so könnte man das über Parameter des
Konstruktors steuern:
class Client {
public:
Client (int autoconnect=1) { if(autoconnect) Connect(); }
virtual ~Client() {}
void Connect() { ShowError(); }
protected:
virtual void ShowError() { cerr << "Client::ShowError()\n"; }
};
class SpecialClient : public Client {
public:
SpecialClient(): Client(0) // kein Autoconnect in Client
{ Connect(); } // Connect erst in SecialClient
protected:
void ShowError() { cerr << "SpecialClient::ShowError()\n"; }
};
Hier wird Connect erst im Konstruktor SpecialClient() aufgerufen, so daß
die richtigen virtuellen Funktionen benutzt werden.
Karl-Heinz Krause
Technical Details
Message-ID:
<45uc8f$aiu@news00.btx.dtag.de>Path:
arc1-ca.pugleaf.net!news00.btx.dtag.de!not-for-mailReferences:
<45qosk$t10@robot.mayn.de>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!news00.btx.dtag.de!not-for-mail From: Krause@btx.dtag.de (Karl-Heinz Krause) Newsgroups: de.comp.lang.c++ Subject: Re: Wiedermal: Virtuelle Methoden Date: 16 Oct 1995 19:36:47 GMT Organization: Telekom Online Internet Gateway Message-ID: <45uc8f$aiu@news00.btx.dtag.de> References: <45qosk$t10@robot.mayn.de> Mime-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8bit X-Sender: 0913148778-0001@btx.dtag.de (Karl-Heinz Krause) X-Newsreader: Forte Free Agent 1.0.82