Klassen offset von der Kind Klasse zu den Eltern Klassen ermitteln
-
Ich wüsste nicht, wie sich hier offsetof anbietet. Eine Lösung für den GCC:
constexpr C* c = reinterpret_cast<C*>(0xDeadBeef); // darf nicht null sein constexpr int offset = reinterpret_cast<char*>(static_cast<A*>(c)) - reinterpret_cast<char*>(c); std::cout << offset << '\n'; constexpr int offset2 = reinterpret_cast<char*>(static_cast<B*>(c)) - reinterpret_cast<char*>(c); std::cout << offset2 << '\n';
-
nwp3 schrieb:
Oder das in eine Funktion tun und constexpr davorschreiben.
Zeigerdifferenzen sind niemals konstante Ausdrücke. reinterpret_cast auch nicht.
-
das ganze soll natürlich für alle möglichen Klassen typen funktionieren.
Also mit polymorphe Klassen (virtual methods), virtual base class etc.Und bei offsetof muss man auf die member zugreifen, das wollte ich wie gesagt nicht.
Und btw. liefert mir in C++ nicht auch &T::member die offset adresse?
-
Nash26 schrieb:
das ganze soll natürlich für alle möglichen Klassen typen funktionieren.
Also mit polymorphe Klassen (virtual methods), virtual base class etc.Wozu brauchst du das?
-
Nash26 schrieb:
das ganze soll natürlich für alle möglichen Klassen typen funktionieren.
Also mit polymorphe Klassen (virtual methods), virtual base class etc.Dann macht die Frage an sich keinen Sinn mehr. Wenn virtual im Spiel ist, wirst du in der Regel eine konkrete Instanz benötigen, um überhaupt eine Aussage machen zu können, diese Information existiert gar nicht zur Compilezeit. daher kann man auch nicht danach fragen. Es kann daher keine sinnvolle Anwendung für diese Information geben. Daher Umformulierung der Gegenfrage von "Wozu brauchst du das?" zu: Wozu meinst du, das zu brauchen?
-
@SeppJ
Dann musst du mir erklären warum es nicht zur Compilezeit geht, bzw. warum eine
konkrete Instanz benötigt wird.
Etwas anderes wäre, wenn du gesagt hättest ich komme nicht an diese Information ran.struct A { int a; }; struct B { int b; virtual fooBar() {} }; struct C : A, B { int c; }; C c; c.fooBar(); // wird eventuell so hier übersetzt => c.__vptr[0]->fooBar(&c); // wo der __vptr sich befindet sollt der compiler wissen.IMHO weiß der Compiler hier ganz genau zur Compilezeit denn offset.
Aber natürlich nur wenn er das Kind Objekt hat.
Klärt mich gerne auf warum das nicht so sein sollte.
-
Ich dachte da primär an virtuelle Vererbung. Mit virtuellen Funktionen lässt sich bestimmt auch eine Gegenbeispiel basteln. Aber mit virtueller Vererbung ist es leicht:
struct A { int a; }; struct B : public virtual A { int b; }; struct C : public virtual A { int c; }; struct D : public B, public C { int d; }; int main() { // Von oben das offsetof Marke Eigenbau int offset = reinterpret_cast<char*>(static_cast<A*>(reinterpret_cast<D*>(0xDeadBeef))) - reinterpret_cast<char*>(reinterpret_cast<C*>(0xDeadBeef)); }Sollte krachen, denn hier muss im vtable nachgeschlagen werden. Aber wir haben keine Instanz. Oder anstatt vtable, wie auch immer das virtual implementiert ist. Das ist eben auch so ein Problem, dass das alles mögliche sein könnte.
-
ok dann gehe ich einen Schritt zurück.
D d;Bezug nehmend auf dein Beispiel:
Wenn ich dieses D Objekt erzeuge, sollt doch der compiler alle offsets kennen (weil er sie ja selbst erzeugt)?
Wenn nein, warum nicht?
Wenn ja, wie komme ich an diese?PS: was sollen diese komischen HexDez zahlen?
-
Nash26 schrieb:
PS: was sollen diese komischen HexDez zahlen?
Einfach nur ein beliebiger Zeiger. Wenn der Ausdruck zur Compilezeit ausgewertet wird, ist es ja egal, ob der Zeiger irgendwann zur Laufzeit einmal gültig ist oder nicht.
-
Nash26 schrieb:
ok dann gehe ich einen Schritt zurück.
D d;Bezug nehmend auf dein Beispiel:
Wenn ich dieses D Objekt erzeuge, sollt doch der compiler alle offsets kennen (weil er sie ja selbst erzeugt)?In diesem einfachen Fall vielleicht, aber nicht allgemein. Was ist der Offset von C zu A? Das ist schon nicht mehr zu beantworten.
Wenn nein, warum nicht?
Weil bei der virtuellen Vererbung das genaue Klassenlayout vom dynamischen Typ abhängt. Wenn das C Teil eines D ist, dann ist der Offset C zu A ein anderer als bei einem einfachen C.
Wenn ja, wie komme ich an diese?
Wie schon oft gesagt: Die Frage macht gar keinen Sinn, weil du nach etwas fragst, was es gar nicht gibt. Wozu sollte man das brauchen?