offsetof - mehrfache vererbung
-
Krauzi schrieb:
--- was mir nicht gerade weiterhilft. Es muss möglich sein!
std::string ist kein POD, damit ist CParent kein POD, damit ist offsetof undefiniert. Punkt. Alles andere interessiert nicht.
-
in meinem beispiel klappt es aber für's erste.
-
Krauzi schrieb:
in meinem beispiel klappt es aber für's erste.
Trotzdem kann dir auf deine Frage keiner eine verlässliche Antwort geben. Wenn im Standard steht dass es undefiniert ist, dann geht es mit Standard-C++ eben nicht.
Wie dein verwendeter Compiler die Sache konkret handhabt, ist eine andere Frage. Das müsstest du den Hersteller fragen. Dass dein Beispiel funktioniert kann auch nur Zufall sein. Es ist eben undefiniert.
-
habs jetzt noch auf mingw oder wie der compiler heißt kompiliert und da hats auch geklappt. Zufall ist das jetzt eher nicht...
-
Krauzi schrieb:
habs jetzt noch auf mingw oder wie der compiler heißt kompiliert und da hats auch geklappt. Zufall ist das jetzt eher nicht...
wenn etwas undefiniert ist, ists einfach nicht definiert.
wenn 2 compiler zufällig das selbe machen, hat das nichts damit zu tun, was "normalerweise" passiert und heißt auch noch lang nicht, dass es nicht "zufällig" ist...void main() { ; }wetten, ich finde mehr als einen compiler, der das hier compiliert?
ist es dadurch definiert?bb
-
Krauzi schrieb:
habs jetzt noch auf mingw oder wie der compiler heißt kompiliert und da hats auch geklappt. Zufall ist das jetzt eher nicht...
dann heißts, das mehrere compiler ähnliche Dinge machen. Es ändert aber gar nichs daran, dass der Standard ganz klar sagt, dass das jeder Compiler so mchen kann wie er will. Und insbesondere bei Vererbung geht dort alles querbeet durcheinander. Da ändert sich auch gerne mal was zwischen 2 Compilerversionen.
Da kannst du noch so sehr mit dem Fuß aufstampfen und rumflennen, dass es doch gehen muss: der Standard sagt nein. Und der Standard hat in jeder Diskussion das letzte Wort.
-
otze schrieb:
Da kannst du noch so sehr mit dem Fuß aufstampfen und rumflennen, dass es doch gehen muss: der Standard sagt nein. Und der Standard hat in jeder Diskussion das letzte Wort.
Außer da wo es geändert wurde.
-
Gib CParent mal eine virtuelle Funktion (beispielsweise einen Destruktor, wo du doch ableiten willst), und kuck, ob das immer noch hält. Im Übrigen sollte der gcc etwas in dieser Art ausspucken:
test.cc: In constructor »CParent::CSub::CSub()«: test.cc:23: Warnung: invalid access to non-static data member »CParent::m_Sub« of NULL object test.cc:23: Warnung: (vielleicht wurde das Makro »offsetof« falsch verwendet)...und du solltest das beachten.
Die Sprache sieht solchen Blödsinn schlicht nicht vor, und es gibt dementsprechend keinen zuverlässigen Weg, das zu machen.
Wenn du dich auf wilde Hacks einlassen willst: --copy erniedrigt copy um sizeof(*copy). Du könntest es mit
size_t offset = offsetof(CParent, CParent::m_Sub); CParent* copy = reinterpret_cast<CParent*>(reinterpret_cast<char*>(this) - offset);versuchen, aber ich übernehme keine Garantie dafür. Sobald das auseinanderfliegt - und das wird es - bist du selbst schuld. Und ganz ehrlich, wenn mir jemand Software andrehen wollte, von der ich wüsste, dass sie solchen Code enthält, könnte der gleich wieder abschwirren.
-
Hi,
Sorry, dass ich nochmal nachfrage, aber ich verstehe das Problem nicht wirklich...
Ich habe über 200 klassen zu wrappen, von denen alle mindestens 10 constructoren haben (max. ableitungen: 3 mal), ich möchte nicht bei jedem constructor hinschreiben: INITIALIZE(<Klassenname>)!
Meintest du da ein template? ... weil als Makro kann ich mir das nicht vorstellen
Da aber alle klassen bereits wegen reflection mit einem macro ausgestattet sind kann ich durch das hinzufügen des im beispiel gezeigten codes diese methode der CParent klasse aufrufen ohne irgendwas im constructor zu ändern.
Ich kann in dem Code keine Initialisierung entdecken, sondern nur den Versuch erkennen den Pointer des CParent-Objektes aus dem Member heraus zu bekommen (und wie @seldon schon sagte funktioniert das so nicht immer) ...
Wenn es um Initialisierung geht, kannst du ja templates und deren Spezialisierung benutzen.
template<class T> struct Initer; template<> struct Initer<Base> : public Base { Initer() // Initer<Base> ist ja zugleich auch Base ;) { this->attr1 = 12; this->attr2 = 0; this->attr3 = "Hello World"; } }; template<> struct Initer<Base2> : public Base2 { Initer() { ... } }; ... Base * ptrBase = new Initer<Base>; Base2 * ptrBase2 = new Initer<Base2>;cu

-
@Krauzi:
Ich verstehe nicht genau was du machen willst, aber es klingt verflixt danach als ob es Murks wäre.Vorschlag: zeig mal den Code ohne
offsetof(), den du vermeiden willst, der aber sicher funktionieren würde. Also die triviale Implementierung.Vielleicht kann dir dann jmd. einen besseren Vorschlag als den von dir geplanten Hack machen.