C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

RTTI-Unverständnis
Goto page 1, 2  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (German)
View previous topic :: View next topic  
Author Message
Georg Maaß
Guest





PostPosted: Sun Jun 06, 2004 3:33 pm    Post subject: RTTI-Unverständnis Reply with quote



Irgendwie geht mir in Zusammenhang mit Methodenaufrufen die
Typinformation verloren, so daß die Downcasts nicht funktionieren.

Das an die Methoden übergebene Argument ist eine Referenz auf abstrakte
Basisklasse. Wenn ich nun eine Methode der abgeleiteten Klasse aufrufe
und ihr als Argument eine Referenz auf sich selbst übergebe, dann
ergeben die Downcasts auf die Referenz immer nur ein Gelingen bei Cast
zu abstrakter Basisklasse, das gleiche Spielchen jedoch mit *this
erkennt die abgeleitete Klasse.

Kurioserweise gilt:
this == &arg
aber auch:
(long) this != (long) &arg

a) Wieso geht mir bei der Referenz die Typinformation verloren?
b) Warum sagt der Vergleichsoperator, die Adressen seine gleich, obwohl
sie doch unterschiedliche Zahlenwerte haben? Das Objekt ist zwar das
gleiche, aber in der Referenz fehlt irgendwie ein wesentliches Stück
Information.

Hier der Testausdruck für das Kuriosum:

std::cerr<<"this "<<((this == &arg) ? "==" :"!=")<<" &arg ==> " <<
((long)this) <<((((long)this) == ((long)&arg))?" == ":" !=
")<<((long)&arg) << std::endl;

Und hier das, was auf std::cerr ausgegeben wird:

this == &arg ==> 135576760 != 135576828

Gruß, Georg
--
Georg Maaß - bioshop.de D-76227 Karlsruhe, Westmarkstraße 82
HTML, XML / JavaScript, C++, Java, PHP, VB / CGI, JSP, ASP, ASP.net
- The ultimate DHTML engine: http://gml-modul.sourceforge.net -
http://sourceforge.net/projects/gml-modul

--
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
Torsten Robitzki
Guest





PostPosted: Sun Jun 06, 2004 3:51 pm    Post subject: Re: RTTI-Unverständnis Reply with quote



Georg Maaß wrote:

Quote:
Irgendwie geht mir in Zusammenhang mit Methodenaufrufen die
Typinformation verloren, so daß die Downcasts nicht funktionieren.

Das an die Methoden übergebene Argument ist eine Referenz auf abstrakte
Basisklasse. Wenn ich nun eine Methode der abgeleiteten Klasse aufrufe
und ihr als Argument eine Referenz auf sich selbst übergebe, dann
ergeben die Downcasts auf die Referenz immer nur ein Gelingen bei Cast
zu abstrakter Basisklasse, das gleiche Spielchen jedoch mit *this
erkennt die abgeleitete Klasse.

Kurioserweise gilt:
this == &arg

Hier wandelt der Compiler die Adresse von arg in den Typen von this.
Quote:
aber auch:
(long) this != (long) &arg

Hier nicht.

Quote:
a) Wieso geht mir bei der Referenz die Typinformation verloren?

Dafür hast Du kein Beispiel gezeigt.

Quote:
b) Warum sagt der Vergleichsoperator, die Adressen seine gleich, obwohl
sie doch unterschiedliche Zahlenwerte haben? Das Objekt ist zwar das
gleiche, aber in der Referenz fehlt irgendwie ein wesentliches Stück
Information.

Wie oben.
Quote:

Hier der Testausdruck für das Kuriosum:

std::cerr<<"this "<<((this == &arg) ? "==" :"!=")<<" &arg ==> "
((long)this) <<((((long)this) == ((long)&arg))?" == ":" !=
")<<((long)&arg) << std::endl;

Und hier das, was auf std::cerr ausgegeben wird:

this == &arg ==> 135576760 != 135576828

Wie kommst Du darauf, das das funktionieren sollte? Welcher compiler
akzeptiert so etwas?

class A {
int i;
};

class B {
};

class C : public A, public B {};

B b;
C c;

wenn der compiler das layout der Klassen z.B. so arangiert, das für C
zuerst der A-Anteil, dann der B Anteil im Speicher abgelegt wird, sollte
geleten

&b == static_cast<B*>(&c);
static_cast<void*>(&b) != static_cast<void*>(&c);

mfg Torsten

--
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
Georg Maaß
Guest





PostPosted: Sun Jun 06, 2004 4:30 pm    Post subject: Re: RTTI-Unverständnis Reply with quote



Torsten Robitzki wrote:
Quote:
Kurioserweise gilt:
this == &arg
Hier wandelt der Compiler die Adresse von arg in den Typen von this.

Warum? Da steht doch gar kein Cast-Operator. Und vorallem, warum gelingt
hier eine Automatische Typwandlung, während eine xpelizite Typwandlung
mittels dynamic_cast nicht funktioniert.

Wenn ich die Funktion so ändere, daß sie einen Zeiger statt einer
Referenz will, dann geht die Typinformation nicht verloren.

Offenbar geht die Typinformation schon vor dem Methodenaufruf bei der
Anwendung des * auf die second-Komponente des Iterators kaputt.

// Funzt bei Funktion mit Zeiger als Argument
p->second->serve(p->second);
// Funzt NICHT bei Funktion mit Referenz als Argument
p->second->serve(*p->second);
^
Da scheint das Übel zu beginnen.

--
Georg Maaß - bioshop.de D-76227 Karlsruhe, Westmarkstraße 82
HTML, XML / JavaScript, C++, Java, PHP, VB / CGI, JSP, ASP, ASP.net
- The ultimate DHTML engine: http://gml-modul.sourceforge.net -
http://sourceforge.net/projects/gml-modul

--
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
Torsten Robitzki
Guest





PostPosted: Sun Jun 06, 2004 6:30 pm    Post subject: Re: RTTI-Unverständnis Reply with quote

Georg Maaß wrote:

Quote:
Torsten Robitzki wrote:

Kurioserweise gilt:
this == &arg

Hier wandelt der Compiler die Adresse von arg in den Typen von this.


Warum? Da steht doch gar kein Cast-Operator. Und vorallem, warum gelingt
hier eine Automatische Typwandlung, während eine xpelizite Typwandlung
mittels dynamic_cast nicht funktioniert.

Wenn ich die Funktion so ändere, daß sie einen Zeiger statt einer
Referenz will, dann geht die Typinformation nicht verloren.

Offenbar geht die Typinformation schon vor dem Methodenaufruf bei der
Anwendung des * auf die second-Komponente des Iterators kaputt.

// Funzt bei Funktion mit Zeiger als Argument
p->second->serve(p->second);
// Funzt NICHT bei Funktion mit Referenz als Argument
p->second->serve(*p->second);
^
Da scheint das Übel zu beginnen.


Wie wäre es den mit einem minimalen Beispiel, bei dem das Problem
auftritt und das man übersetzen kann? Die Funktion serve() ist in einer
Basisklasse deklariert und erwartet einen Zeiger/Referenz auf eine
andere Basisklasse? Gibt es mindestens eine virtuelle Funktion in beiden
Basisklassen?

mfg Torsten

--
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





PostPosted: Sun Jun 06, 2004 6:35 pm    Post subject: Re: RTTI-Unverständnis Reply with quote

Georg Maaß wrote:

Quote:
Irgendwie geht mir in Zusammenhang mit Methodenaufrufen die
Typinformation verloren, so daß die Downcasts nicht funktionieren.

Das an die Methoden übergebene Argument ist eine Referenz auf
abstrakte Basisklasse. Wenn ich nun eine Methode der abgeleiteten
Klasse aufrufe und ihr als Argument eine Referenz auf sich selbst
übergebe, dann ergeben die Downcasts auf die Referenz immer nur ein
Gelingen bei Cast zu abstrakter Basisklasse, das gleiche Spielchen
jedoch mit *this erkennt die abgeleitete Klasse.

Mir ist nicht so ganz klar, was du meinst. Könntest du ein kurzes
Beispiel dafür posten?

Quote:

Kurioserweise gilt:
this == &arg
aber auch:
(long) this != (long) &arg

a) Wieso geht mir bei der Referenz die Typinformation verloren?

Wie kommst du darauf?

Quote:
b) Warum sagt der Vergleichsoperator, die Adressen seine gleich,
obwohl sie doch unterschiedliche Zahlenwerte haben?

Sie sind von unterschiedlichem Typ. Diese Information hast du dem
Compiler aber durch den Cast weggenommen, so daß er den Vergleich nicht
mehr so durchführen kann, wie er sollte.

Quote:
Das Objekt ist zwar das gleiche, aber in der Referenz fehlt irgendwie
ein wesentliches Stück Information.

Ganz im Gegenteil. Sie enthält "ein wesentliches Stück Information", das
druch deinen Cast nach long verloren geht. Der Basisklassenteil muß
nicht unbedingt am Anfang des Objekts beginnen, sondern evtl. dahinter.
Bei Mehrfachableitung geht das meist für eine der Basisklassen gar
nicht anders. Deshalb muß für den Vergleich eines Basisklassenzeigers
mit einem Zeiger auf eine abgeleitete Klasse eine der beiden Adressen
an diesen Offset angepasst werden.

Quote:
Hier der Testausdruck für das Kuriosum:

std::cerr<<"this "<<((this == &arg) ? "==" :"!=")<<" &arg ==> "
((long)this) <<((((long)this) == ((long)&arg))?" == ":" !=
")<<((long)&arg) << std::endl;

Und hier das, was auf std::cerr ausgegeben wird:

this == &arg ==> 135576760 != 135576828

Gruß, Georg

--
First they ignore you. Then they laugh about you.
Then they fight you. And then you win.
(Mahatma Gandhi)

--
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
Markus Breuer
Guest





PostPosted: Mon Jun 07, 2004 8:02 am    Post subject: Re: RTTI-Unverständnis Reply with quote

Georg Maaß schrieb:

Quote:
Torsten Robitzki wrote:

Kurioserweise gilt:
this == &arg

Hier wandelt der Compiler die Adresse von arg in den Typen von this.


Warum? Da steht doch gar kein Cast-Operator. Und vorallem, warum gelingt
hier eine Automatische Typwandlung, während eine xpelizite Typwandlung
mittels dynamic_cast nicht funktioniert.

Du musst bedenken, dass der this-Zeiger (vom Wert her) unterschiedlich
ist, je nachdem ob er vom Typ der Basisklasse oder der abgeleiteten
Klasse ist. Ein cast nach long nimmt das, was gerade da steht.

class Foo {};

class Bar : Foo {};

Bar obj1;
static_cast<void*>( &obj1 );

=> keine berücksichtigung des Typ

Bar* p1 = &obj1; // zeiger auf den Bar-Teil
Foo* p2 = &obj1; // Zeiger auf den Foo-Teil

es gilt

static_cast<void*>( p1 ) ist ungleich static_cast<void*>( p2 )

Erläuterung:
Ein Foo ist zeitgleich auch ein Bar, d.h. es enthält einen Bar-Anteil.
Der Compiler erkennt die Verwandschaft und nimmt eine automatische
Konvertierung vor, so dass der kleinste gemeinsame Nenner (in diesem
Fall die Basisklasse Bar) verglichen wird.

Gruß Markus

--
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





PostPosted: Mon Jun 07, 2004 11:22 am    Post subject: Re: RTTI-Unverständnis Reply with quote

Moin,

Markus Breuer schrieb...
Quote:
Du musst bedenken, dass der this-Zeiger (vom Wert her) unterschiedlich
ist, je nachdem ob er vom Typ der Basisklasse oder der abgeleiteten
Klasse ist. Ein cast nach long nimmt das, was gerade da steht.

class Foo {};

class Bar : Foo {};

Bar obj1;
static_cast<void*>( &obj1 );

=> keine berücksichtigung des Typ

Bar* p1 = &obj1; // zeiger auf den Bar-Teil
Foo* p2 = &obj1; // Zeiger auf den Foo-Teil

es gilt

static_cast<void*>( p1 ) ist ungleich static_cast<void*>( p2 )

Hast Du das mal ausprobiert? Bei mir stimmt die Aussage nämlich nicht.
Ich habe
static_cast<void*>(p1) == static_cast<void*>(p2)
als Ergebnis.


Quote:
Erläuterung:
Ein Foo ist zeitgleich auch ein Bar, d.h. es enthält einen Bar-Anteil.

Umgekehrt, ein Bar enthält auch einen Foo Teil. Bei einfacher Vererbung
ist eine Adressanpassung nicht notwendig, da die abgeleitete Klasse
einfach hinter die Basisklasse gepackt wird. Die abgeleitete Klasse kann
aber niemals ohne die Basis existieren! Aus die Basis kann direkt ohne
Adressanpassung gecastet werden, da sie sowieso vor der abgeleiteten
Klasse im Speicher liegt.
Bei Mehrfachvererbung sieht die Sache dann schon wieder anders aus.


- 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
Markus Breuer
Guest





PostPosted: Mon Jun 07, 2004 12:37 pm    Post subject: Re: RTTI-Unverständnis Reply with quote

Heinz Saathoff schrieb:

Quote:
static_cast<void*>( p1 ) ist ungleich static_cast<void*>( p2 )


Hast Du das mal ausprobiert? Bei mir stimmt die Aussage nämlich nicht.
Ich habe
static_cast<void*>(p1) == static_cast<void*>(p2)
als Ergebnis.

Konkret ausprobiert habe ich das nicht. Nach meinem Verständnis ist das
im allgemeinen nicht erlaubt, d.h. man muss davon ausgehen, dass die
Gleichheit nicht in jedem Fall gegeben ist. Ich hatte die Ungleichhat
bewusst verbal ausgedrückt, damit es keine Verwechslung mit dem
!=-operator gibt.

Quote:
Erläuterung:
Ein Foo ist zeitgleich auch ein Bar, d.h. es enthält einen Bar-Anteil.


Umgekehrt, ein Bar enthält auch einen Foo Teil. Bei einfacher Vererbung
ist eine Adressanpassung nicht notwendig, da die abgeleitete Klasse
einfach hinter die Basisklasse gepackt wird. Die abgeleitete Klasse kann
aber niemals ohne die Basis existieren! Aus die Basis kann direkt ohne
Adressanpassung gecastet werden, da sie sowieso vor der abgeleiteten
Klasse im Speicher liegt.

Irtumm ...

Quote:
Bei Mehrfachvererbung sieht die Sache dann schon wieder anders aus.

.... eben aus diesem Grund kann man davon ausgehen, dass der cast im
Allgemeinen nicht zulässig ist.

Gruß Markus

--
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
Marcel Müller
Guest





PostPosted: Mon Jun 07, 2004 12:51 pm    Post subject: Re: RTTI-Unverständnis Reply with quote

Hi!

Heinz Saathoff wrote:

[...]
Quote:
static_cast<void*>( p1 ) ist ungleich static_cast<void*>( p2 )

Hast Du das mal ausprobiert? Bei mir stimmt die Aussage nämlich nicht.
Ich habe
static_cast<void*>(p1) == static_cast<void*>(p2)
als Ergebnis.

Es ist undefiniert.


Quote:
Umgekehrt, ein Bar enthält auch einen Foo Teil. Bei einfacher Vererbung
ist eine Adressanpassung nicht notwendig, da die abgeleitete Klasse
einfach hinter die Basisklasse gepackt wird. Die abgeleitete Klasse kann
aber niemals ohne die Basis existieren! Aus die Basis kann direkt ohne
Adressanpassung gecastet werden, da sie sowieso vor der abgeleiteten
Klasse im Speicher liegt.
Bei Mehrfachvererbung sieht die Sache dann schon wieder anders aus.

Der Compiler darf auch bei Einfachvererbung davon gebrauch machen. Das
hängt davon ab, wie der Compiler die virtuellen Funtionen und
Basisklassen implementiert.


Marcel

--
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
Falk Tannhäuser
Guest





PostPosted: Mon Jun 07, 2004 1:14 pm    Post subject: Re: RTTI-Unverständnis Reply with quote

Heinz Saathoff wrote:
Quote:

Umgekehrt, ein Bar enthält auch einen Foo Teil. Bei einfacher Vererbung
ist eine Adressanpassung nicht notwendig, da die abgeleitete Klasse
einfach hinter die Basisklasse gepackt wird. Die abgeleitete Klasse kann
aber niemals ohne die Basis existieren! Aus die Basis kann direkt ohne
Adressanpassung gecastet werden, da sie sowieso vor der abgeleiteten
Klasse im Speicher liegt.

Manchmal ja, manchmal nein.
_______________________________________________________________
#include <iostream>
#include <ostream>

class Foo
{
int i;
};

class Bar : public Foo
{
public:
virtual ~Bar() {}
};

int main()
{
Bar obj;

Bar* pB = &obj;
Foo* pF = &obj;

void* pvB = pB;
void* pvF = pF;

std::cout.setf(std::ios::boolalpha);
std::cout << pvB << ' ' << pvF << ' ' << (pvB==pvF) << 'n';
return 0;
}
_______________________________________________________________
zeigt bei mir die Ausgabe
"0x22f040 0x22f044 false"

Wenn jedoch die Klasse Foo leer ist, kriege ich
"0x22f040 0x22f040 true", da offenbar leere Basisklassen
wegoptimiert werden.
Gleichheit kriege ich weiterhin, wenn ich Foo eine virtuelle
Funktion spendiere oder aber Bar nicht polymorph mache.
Bei virtueller Vererbung kann alles noch wieder anders aussehen,
mit anderen Compilern (ich habe g++ 3.3.1 cygwin) sowieso - es
ist also auf nichts Verlass.

MfG
Falk

--
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





PostPosted: Mon Jun 07, 2004 1:15 pm    Post subject: Re: RTTI-Unverständnis Reply with quote

Moin,

Markus Breuer schrieb...
Quote:
Umgekehrt, ein Bar enthält auch einen Foo Teil. Bei einfacher Vererbung
ist eine Adressanpassung nicht notwendig, da die abgeleitete Klasse
einfach hinter die Basisklasse gepackt wird. Die abgeleitete Klasse kann
aber niemals ohne die Basis existieren! Aus die Basis kann direkt ohne
Adressanpassung gecastet werden, da sie sowieso vor der abgeleiteten
Klasse im Speicher liegt.

Irtumm ...

Wir reden hier aber von dieser Ableitung, oder? :
Quote:
class Foo {};

class Bar : Foo {};


Ein Bar ist immer auch ein Foo (enthält ein Foo), deshalb geht

Bar bar_obj;
Foo *fpt = static_cast<Foo*>(&bar_obj);

auch, während der umgekehrte Schluß nicht gültig ist, wie bei

Foo foo_obj;
Bar *bpt = static_cast<Bar*>(&foo_obj); // ungültig

foo_obj ist niemals legalerweise ein Bar.


- 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





PostPosted: Mon Jun 07, 2004 1:21 pm    Post subject: Re: RTTI-Unverständnis Reply with quote

Marcel Müller schrieb...
Quote:
Hast Du das mal ausprobiert? Bei mir stimmt die Aussage nämlich nicht.
Ich habe
static_cast<void*>(p1) == static_cast<void*>(p2)
als Ergebnis.

Es ist undefiniert.

Richtig, denn
[snip]
Quote:
Bei Mehrfachvererbung sieht die Sache dann schon wieder anders aus.

Der Compiler darf auch bei Einfachvererbung davon gebrauch machen. Das
hängt davon ab, wie der Compiler die virtuellen Funtionen und
Basisklassen implementiert.

Aber es dürfte eine weit verbreitete Methode sein, bei einfacher
Ableitung Speicherbereiche einfach aneinander zu ketten und damit beim
Upcast immer den gleichen this-Pointer zu kriegen.


- 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





PostPosted: Mon Jun 07, 2004 1:41 pm    Post subject: Re: RTTI-Unverständnis Reply with quote

Falk Tannhäuser schrieb...
Quote:
Umgekehrt, ein Bar enthält auch einen Foo Teil. Bei einfacher Vererbung
ist eine Adressanpassung nicht notwendig, da die abgeleitete Klasse
einfach hinter die Basisklasse gepackt wird. Die abgeleitete Klasse kann
aber niemals ohne die Basis existieren! Aus die Basis kann direkt ohne
Adressanpassung gecastet werden, da sie sowieso vor der abgeleiteten
Klasse im Speicher liegt.

Manchmal ja, manchmal nein.
[snip Beispiel]


Quote:
zeigt bei mir die Ausgabe
"0x22f040 0x22f044 false"
gibt auch false bei mir


Quote:
Wenn jedoch die Klasse Foo leer ist, kriege ich
"0x22f040 0x22f040 true", da offenbar leere Basisklassen
wegoptimiert werden.
Bei mir anscheinend nicht, immer noch false


Quote:
Gleichheit kriege ich weiterhin, wenn ich Foo eine virtuelle
Funktion spendiere oder aber Bar nicht polymorph mache.
Genau so hier.


Quote:
Bei virtueller Vererbung kann alles noch wieder anders aussehen,
mit anderen Compilern (ich habe g++ 3.3.1 cygwin) sowieso - es
ist also auf nichts Verlass.
Hast recht. Wie aber diese Beispiele zeigen, kann ein cast eben auch zu

gleichen Pointern führen, oder eben nicht. Aus diesem Grund stimmt aber
auch die Aussage von Markus Breuer:
Quote:
es gilt
static_cast<void*>( p1 ) ist ungleich static_cast<void*>( p2 )
nicht, weil auch dies nicht garantiert gilt. Deshalb meine Frage, ob er

es ausprobiert hatte.


- 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
Markus Breuer
Guest





PostPosted: Mon Jun 07, 2004 9:21 pm    Post subject: Re: RTTI-Unverständnis Reply with quote

Heinz Saathoff wrote:

Quote:
Wir reden hier aber von dieser Ableitung, oder? :

class Foo {};

class Bar : Foo {};



Ein Bar ist immer auch ein Foo (enthält ein Foo), deshalb geht

Bar bar_obj;
Foo *fpt = static_cast<Foo*>(&bar_obj);

Eigentlich müsste es reinterpret_cast<> sein, das entspricht dem
urspünglichem C-cast. Verhält es sich da auch so?

Quote:
auch, während der umgekehrte Schluß nicht gültig ist, wie bei

Foo foo_obj;
Bar *bpt = static_cast<Bar*>(&foo_obj); // ungültig

foo_obj ist niemals legalerweise ein Bar.

Im Prinzip geht es darum, dass der Basisklassenanteil immer relativ zum
this-Zeiger des Objekts liegt. Der Zeiger des Basisklassenteils ist
demnach ein anderer, als der des ganzen Objekts. Beim upcast sagst du
dem Compiler, welche Klasse du im Visier hast und er macht die aus dem
aktuellen this-Zeiger + Offset einen neuen Zeiger ohne Offset. Das
passiert zumindest bei dem C-like-cast, während der static_cast (mein
Fehler) implizit die Offset-Verschiebung berücksichtigt.

Das dieses Problem existiert, demonstriert der Anfang dieses Threads. Wo
und wie bzw. unter welchen Umständen die Zeiger gleich bleiben, ist
undefiniert. Da das Verhalten undefiniert ist, macht es auch keinen Sinn
darüber zu senieren. Auch wenn es in einigen Fällen okay ist, lässt sich
daraus keine allgemeine Regel definieren.

Gruß Markus

--
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





PostPosted: Tue Jun 08, 2004 7:12 am    Post subject: Re: RTTI-Unverständnis Reply with quote

Moin,

Markus Breuer schrieb...
Quote:
Ein Bar ist immer auch ein Foo (enthält ein Foo), deshalb geht

Bar bar_obj;
Foo *fpt = static_cast<Foo*>(&bar_obj);

Eigentlich müsste es reinterpret_cast<> sein, das entspricht dem
urspünglichem C-cast. Verhält es sich da auch so?

In diesem Fall geht beides. Es geht sogar ganz ohne cast, da der Upcast
immer automatisch durchgeführt wird. Dadurch wird ja auch die Behandlung
der Polymorphie erst schön.


Quote:
auch, während der umgekehrte Schluß nicht gültig ist, wie bei

Foo foo_obj;
Bar *bpt = static_cast<Bar*>(&foo_obj); // ungültig

foo_obj ist niemals legalerweise ein Bar.

Im Prinzip geht es darum, dass der Basisklassenanteil immer relativ zum
this-Zeiger des Objekts liegt.

Soweit richtig.

Quote:
Der Zeiger des Basisklassenteils ist
demnach ein anderer, als der des ganzen Objekts.

Und dies muß nicht stimmen, kann aber. Wie schon geschrieben wurde,
kann/sollte man sich nicht darauf verlassen.

Quote:
Beim upcast sagst du
dem Compiler, welche Klasse du im Visier hast und er macht die aus dem
aktuellen this-Zeiger + Offset einen neuen Zeiger ohne Offset. Das
passiert zumindest bei dem C-like-cast, während der static_cast (mein
Fehler) implizit die Offset-Verschiebung berücksichtigt.

Wie gesagt, ist abhänging von der Art der Klassen (ohne/mit virtuellen
Funktionen, einfach/mehrfach Vererbung). Das hat jetzt nichts mit
static_cast oder reinterpret_cast oder kein cast (Upcast braucht ja
keinen expliziten cast) zu tun. Wenn eine Zeigeranpassung notwendig ist,
wird der Compiler das durchführen.


Quote:
Das dieses Problem existiert, demonstriert der Anfang dieses Threads. Wo
und wie bzw. unter welchen Umständen die Zeiger gleich bleiben, ist
undefiniert. Da das Verhalten undefiniert ist, macht es auch keinen Sinn
darüber zu senieren. Auch wenn es in einigen Fällen okay ist, lässt sich
daraus keine allgemeine Regel definieren.

Keine allgemeine für jeden Compiler. Aber es kann Sinn machen, sich
mögliche Implementierungsmechanismen anzuschauen, auch um den Aufwand
abzuschätzen. Ich habe mal einen kleinen Test mit virtueller Ableitung
gemacht und mir angeschaut, wie der Compiler eigentlich mit den
unterschiedlichen Offsets beim Upcast umgeht. Da der Abstand nicht mehr
zur Compilezeit fest steht, arbeitet er hier mit weiteren Tabellen.
Was ich daraus (zumindest für meinen Compiler) ableite: virtuelle
Ableitungen erfordern weit höheren Aufwand sowohl an Codegröße als auch
an Laufzeit.


- 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
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (German) All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.