🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: de.comp.lang.c++
4 messages
4 total messages Started by Roman 'RoB' Bartke Sun, 15 Oct 1995 10:47
Wiedermal: Virtuelle Methoden
#576
Author: Roman 'RoB' Bartke
Date: Sun, 15 Oct 1995 10:47
57 lines
2011 bytes
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 ist im Beispiel tragisch, da der Konstruktor bei neudefinierten
virtuellen Methoden nicht automatisch "connecten" darf...

Wo kann man die Antwort darauf ggf. nachlesen?

-- 
  eMail: rob@robot.mayn.de; rob@informatik.uni-wuerzburg.de          PGP on
 whoami: main(i){putchar(471252544>>i*5&31|!!(i%6)<<6)&&main(++i);}  demand
Re: Wiedermal: Virtuelle Methoden
#580
Author: Benjamin Baermann
Date: Sun, 15 Oct 1995 21:37
21 lines
1265 bytes
In <45qosk$t10@robot.mayn.de> rob@robot.mayn.de (Roman 'RoB' Bartke) writes:
>"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.

Aeh... vielleicht hab ich ja was komplett falsch verstanden... aber
woher soll denn die Basisklasse die Funktionen von SpezialClient kennen,
seien sie jetzt virtuell oder nicht?

Vielleicht hab ich ja auch Deine Frage einfach nicht verstanden...

.... verwirrt, Benni
-- 
benni@informatik.uni-frankfurt.de|http://www.uni-frankfurt.de/gnomic/hello.html
    "Deshalb, Leute, die glauben, dass Computer werden nicht koennen, wie
      Menschen zu denken, auch glaubt nicht in Maschine-Uebersetzung."
Re: Wiedermal: Virtuelle Methoden
#587
Author: Juergen Kraemer
Date: Mon, 16 Oct 1995 14:30
68 lines
2531 bytes
Hallo!

Roman 'RoB' Bartke (rob@robot.mayn.de) wrote:
: 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 ist im Beispiel tragisch, da der Konstruktor bei neudefinierten
: virtuellen Methoden nicht automatisch "connecten" darf...

Die Klasse "Client" kann keine virtuellen Funktionen von "SpecialClient"
aufrufen. Die virtuellen Funktionen einer Klasse werden in der sogenannten
'Virtual Methods Table' (VMT) abgelegt. Diese Tabelle wird vom Konstruktor
der entsprechenden Klasse angelegt. Bei einer abgeleiteten Klasse werden,
wie Dein Beispiel auch zeigt, die Konstruktoren der Basisklassen vor
demjenigen der abgeleiteten aufgerufen. Das bedeutet, dass die VMT der
abgeleiteten Klasse zu diesem Zeitpunkt noch nicht erzeugt worden sein
kann und daher den Basisklassen unbekannt sein muss. Literatur dazu gibt
es z.B. von Stroustrup, Lippman und einigen anderen, wahlweise auf Deutsch
oder Englisch.

mfg
Juergen
Re: Wiedermal: Virtuelle Methoden
#591
Author: Karl-Heinz Krause
Date: Mon, 16 Oct 1995 19:36
96 lines
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
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads