Ich weiß, dass das Speicherlayout der Mehrfachvererbung nicht definiert ist, also sollte ich mich nicht darauf verlassen. Kann ich mich jedoch in einem speziellen Fall darauf verlassen? Das heißt, eine Klasse hat nur eine "echte" Superklasse. Alle anderen sind "leere Klassen", d. H. Klassen, die weder Felder noch virtuelle Methoden haben (d. H. Sie haben nur nicht-virtuelle Methoden). In diesem Fall sollten diese zusätzlichen Klassen nichts zum Speicherlayout der Klasse hinzufügen. (Konkreter, in der C++ 11 Formulierung, hat die Klasse Standard-Layout)C++ Mehrfachvererbung Speicherlayout mit "Leere Klassen"
Kann ich daraus schließen, dass alle Superklassen keinen Offset haben? Hier z.B .:
#include <iostream>
class X{
int a;
int b;
};
class I{};
class J{};
class Y : public I, public X, public J{};
int main(){
Y* y = new Y();
X* x = y;
I* i = y;
J* j = y;
std::cout << sizeof(Y) << std::endl
<< y << std::endl
<< x << std::endl
<< i << std::endl
<< j << std::endl;
}
, Y
ist die Klasse mit X
die einzige wirkliche Basisklasse zu sein. Die Ausgabe des Programms (wenn auf Linux mit g ++ 4.6 kompiliert) ist wie folgt:
0x233f010
0x233f010
0x233f010
0x233f010
Wie ich festgestellt habe, gibt es keine poi nter Anpassung. Aber ist diese Implementierung spezifisch oder kann ich mich darauf verlassen? Wenn ich ein Objekt vom Typ I
(und ich weiß, dass nur diese Klassen existieren) bekomme, kann ich dann reinterpret_cast
verwenden, um es in X
zu konvertieren?
Meine Hoffnungen sind, dass ich mich darauf verlassen konnte, weil die Spezifikation besagt, dass die Größe eines Objekts mindestens ein Byte sein muss. Daher kann der Compiler kein anderes Layout auswählen. Wenn es I
und J
hinter den Mitgliedern von X
layout, dann wäre ihre Größe Null (weil sie keine Mitglieder haben). Daher ist die einzige vernünftige Wahl, alle Superklassen ohne Offset auszurichten.
Bin ich richtig oder spiele ich mit dem Feuer, wenn ich reinterpret_cast von I
bis X
hier benutze?
Speicherlayout der Vererbung, einzelne oder mehrere, leere Basen oder nicht, ist nicht definiert. –
Ich würde sagen, du spielst mit Feuer, weil du versuchst, ein sehr seltsames Konstrukt zu machen, das sicherlich jedem, der es in Zukunft verstehen muss, Schmerz und Elend bringt, auch wenn es beim Upgrade nicht kaputt geht Dein Übersetzer! – Rook
Zum Glück sind Ihre Aussagen in C++ 11 nicht mehr korrekt, siehe die Antwort :) – gexicide