Mehrfachvererbung: Unerwartetes Ergebnis nach Umwandlung von void * in die 2. Basisklasse

Mein Programm muss void * verwenden, um Daten oder Objekte in einer dynamischen Aufrufsituation zu transportieren, damit es auf Daten beliebigen Typs, auch auf primitive Typen, verweisen kann. Vor kurzem habe ich jedoch festgestellt, dass der Vorgang des Herunterwerfens dieser ungültigen * Werte bei Klassen mit mehreren Basisklassen fehlschlägt und mein Programm sogar abstürzt, nachdem Methoden für diese heruntergeworfenen Zeiger aufgerufen wurden, selbst wenn die Speicheradressen korrekt zu sein scheinen. Der Absturz passiert beim Zugriff auf "vtable".

Also habe ich einen kleinen Testfall erstellt, Umgebung ist gcc 4.2 unter Mac OS X:

class Shape {
public:
    virtual int w() = 0;
    virtual int h() = 0;
};

class Square : public Shape {
public:
    int l;
    int w() {return l;}
    int h() {return l;}
};

class Decorated {
public:
    int padding;
    int w() {return 2*padding;}
    int h() {return 2*padding;}
};

class DecoratedSquare : public Square, public Decorated {
public:
    int w() {return Square::w() + Decorated::w();}
    int h() {return Square::h() + Decorated::h();}
};


#include <iostream>

template <class T> T shape_cast(void *vp) {
//    return dynamic_cast<T>(vp);   // not possible, no pointer to class type
//    return static_cast<T>(vp);
//    return T(vp);
//    return (T)vp;
    return reinterpret_cast<T>(vp);
}

int main(int argc, char *argv[]) {
    DecoratedSquare *ds = new DecoratedSquare;
    ds->l = 20;
    ds->padding = 5;
    void *dsvp = ds;

    std::cout << "Decorated (direct)" << ds->w() << "," << ds->h() << std::endl;

    std::cout << "Shape " << shape_cast<Shape*>(dsvp)->w() << "," << shape_cast<Shape*>(dsvp)->h() << std::endl;
    std::cout << "Square " << shape_cast<Square*>(dsvp)->w() << "," << shape_cast<Square*>(dsvp)->h() << std::endl;
    std::cout << "Decorated (per void*) " << shape_cast<Decorated*>(dsvp)->w() << "," << shape_cast<Decorated*>(dsvp)->h() << std::endl;
    std::cout << "DecoratedSquare " << shape_cast<DecoratedSquare*>(dsvp)->w() << "," << shape_cast<DecoratedSquare*>(dsvp)->h() << std::endl;
}

erzeugt die folgende Ausgabe:

Decorated (direct)30,30
Shape 30,30
Square 30,30
Decorated (per void*) 73952,73952
DecoratedSquare 30,30

Wie Sie sehen, ist das Ergebnis "Dekoriert (per void *)" völlig falsch. Es sollte auch 30,30 wie in der ersten Zeile sein.

Unabhängig davon, welche Cast-Methode ich in shape_cast () verwende, erhalte ich immer dieselben unerwarteten Ergebnisse für das dekorierte Teil. Irgendetwas stimmt mit dieser Lücke nicht *.

Nach meinem Verständnis von C ++ sollte dies tatsächlich funktionieren. Gibt es eine Chance, dies mit der Leere * zum Laufen zu bringen? Kann das ein Fehler in gcc sein?

Vielen Dank

Antworten auf die Frage(3)

Ihre Antwort auf die Frage