Sie können vielleicht die Tatsache ausnutzen, dass der Compiler bei einem Cast von einem Zeiger auf eine Basisklasse, die nicht die einzige Basisklasse ist, den Zeiger so anpasst, dass er auf den Anfang der Superklasse zeigt. Wenn Ihr "c"-Mitglied also am Anfang einer Basisklasse existiert, könnten Sie einen Trick anwenden wie:
struct myStructBase1 { int a; };
struct myStructBase2 { int b; };
struct myStructBase3 { int c; };
struct myStruct : public myStructBase1,myStructBase2,myStructBase3 {
int d;
};
int main() {
myStruct my;
int * bptr = &my.b;
int * cptr = &my.c;
// The only dirty part in the code...
myStructBase2 * base2ptr = reinterpret_cast<myStructBase2*> (bptr);
myStructBase3 * base3ptr = reinterpret_cast<myStructBase3*> (cptr);
// In each (myStruct*) cast the pointers are adjusted to point to the super class.
cout << &my << endl <<
(myStruct*) base2ptr << endl <<
(myStruct*) base3ptr << endl;
return 0;
}
// Output:
// 0xbfbc779c
// 0xbfbc779c
// 0xbfbc779c
Die Voraussetzung dafür ist, dass dies funktioniert: Wenn ein Mitglied das erste Mitglied in seiner Klasse ist, dann ist seine Adresse in einem Objekt gleich der Adresse des Objekts (dieser Klasse). Ich bin mir nicht sicher, ob das wahr ist.
EDIT: Es sollte gelten, wenn die Wrapper-Basisklassen PODs sind. Nach folgenden Änderungen:
struct myStructBase1 { int a; virtual void g() {} };
struct myStructBase2 { int b; virtual void f() {} };
struct myStructBase3 { int c; };
struct myStruct : public myStructBase1,myStructBase2,myStructBase3 {
int d;
virtual void h() {}
};
Die Ausgabe ist:
0xbfa305f4
0xbfa305f8
0xbfa305f4
Für das c-Mitglied gilt die Einschränkung weiterhin. Im Allgemeinen lautet die Antwort also: Ja, es gibt eine alternative Möglichkeit. Allerdings ist die Definition einer Basisklasse für jedes "reversible"-Mitglied wahrscheinlich nicht der richtige Weg.