PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [C++]Basisklassen-Pointer und Mehrfachvererbung


Gast
2007-12-06, 16:52:57
Hi Leute,

ich glaube ich habe eine ungeheuerliche Entdeckung gemacht. Nehmen wir an, ich habe zwei Klassen, A und B. A hat einen Member x vom Typ int, B einen Member y ebenfalls vom Type int. Eine dritte Klasse C erbt von beiden und hat damit beide Member:

class A
{
private:
int x;
public:
int get_x() {return x;}
};

class B
{
private:
int y;
public:
int get_y() {return y;}
};

class C : public A, public B
{
//...
};

Sei nun pc ein Pointer auf eine Instanz von C, und seien bei dieser Instanz x=5 und y=1, d.h. pc->x=5 und pc->y=1. Jetzt konvertiere ich pc in einen Pointer vom Typ B* und frage den Wert von y ab:

B* base = (B*) pc;
int value_of_y = base->get_y();

Kann es sein, daß value_of_y dann nicht den Wert von y zugewiesen bekommt, sondern den von x? D.h. nicht 1 wird, sondern 5? Weil die Methode B::get_y() den Member y an der falschen Speicherposition erwartet, nämlich da wo der Instanz-Pointer (hier base) hinzeigt, während bei der Instanz von C der Member y aber eine Position weiter liegt?
Ich kriege nämlich immer 5 zurück, obwohl ich 1 erwartet hätte...

Gast
2007-12-06, 17:19:43
>>B* base = (B*) pc;

mach da mal (B*) weg.

Gast
2007-12-06, 18:17:40
der Fehler lag woanders: pc war gar nicht vom Typ C*, sondern vom Typ A*, es fand also eine Konvertierung A* -> B* statt, ohne Involvierung von C. Jetzt habe ich pc zuerst nach C* konvertiert, jetzt geht's :)

malte.c
2007-12-06, 21:20:18
B* base = (B*) pc;

C-Casts und Mehrfachvererbung vertragen sich nicht wirklich gut. Nimm im Zweifelsfall B* base = dynamic_cast<B*>(pc);. Und wenn Du schon dabei bist, schau Dir auch mal static_cast, const_cast und reinterpret_cast an. Mit diesen lässt sich ziemlich exakt ausdrücken, was man eigentlich vorhat, so dass man ganz auf die C-Casts verzichten kann.

Coda
2007-12-06, 21:59:00
C-Casts und Mehrfachvererbung vertragen sich nicht wirklich gut.
Eigentlich schon, man muss halt "wissen was man macht" (tm)

Nimm im Zweifelsfall B* base = dynamic_cast<B*>(pc);
Hmm. RTTI braucht Performance.

Und wenn Du schon dabei bist, schau Dir auch mal static_cast, const_cast und reinterpret_cast an. Mit diesen lässt sich ziemlich exakt ausdrücken, was man eigentlich vorhat, so dass man ganz auf die C-Casts verzichten kann.
Guter Tipp, aber in der Praxis bin ich leider zu faul dazu :redface:

The_Invisible
2007-12-06, 22:05:58
2 böse sachen auf einmal, kann ja gar nicht gut gehen ;)

mfg