2011-12-24 8 views
7

Utworzono prosty program demonstrujący błąd środowiska wykonawczego, który otrzymuję za pomocą aplikacji Qt, która korzysta z dziedziczenia wielokrotnego. Drzewo dziedziczenia wygląda następująco:Niepowodzenie sprawdzania podczas uruchamiania # 0 - Wartość ESP nie została poprawnie zapisana w wywołaniu funkcji

QGraphicsItem (abstract) 
     \ 
    QGraphicsLineItem  MyInterface (abstract) 
       \  /
        \  /
        MySubclass 

A oto kod:

/* main.cpp */ 
#include <QApplication> 
#include <QGraphicsScene> 
#include <QGraphicsLineItem> 

//simple interface with one pure virtual method 
class MyInterface 
{ 
public: 
    virtual void myVirtualMethod() = 0; 
}; 

//Multiple inheritance subclass, simply overrides the interface method 
class MySubclass: public QGraphicsLineItem, public MyInterface 
{ 
public: 
    virtual void myVirtualMethod() { } 
}; 

int main(int argc, char** argv) 
{ 
    QApplication app(argc, argv); //init QApplication 
    QGraphicsScene *scene = new QGraphicsScene(); //create scene 

    scene->addItem(new MySubclass()); // add my subclass to the scene 

    Q_FOREACH(QGraphicsItem *item, scene->items()) // should only have one item 
    { 
    MyInterface *mInterface = (MyInterface*)item; // cast as MyInterface 
    mInterface->myVirtualMethod(); // <-- this causes the error 
    } 
    return 0; 
} 

debugowanie w wizualnych wyników studio w runtime error kiedy moja metoda interfejsu nazywa się:

Run-Time Check Failure #0 - The value of ESP was not properly 
    saved across a function call. This is usually a result of 
    calling a function declared with one calling convention with 
    a function pointer declared with a different calling convention. 

Wszelkie wyobrażasz sobie, na czym polega problem?

Odpowiedz

8

Ponieważ używasz wielokrotnego dziedziczenia, wskaźnik do czego oczekuje się MyInterface*vftable jest rzeczywiście wskaźnik do QGraphicsLineItem vftable.

dynamic_cast rozwiąże problemu, ponieważ będzie to powrót prawidłowej vftable

MyInterface* mInterface = dynamic_cast<MyInterface*>(item); 

prosty przykład:

class A 
{ 
public: 
    virtual void foo() = 0; 
}; 

class B 
{ 
public: 
    virtual void goo() {}; 
}; 

class C : public B, public A 
{ 
public: 
    virtual void foo() {}; 
}; 

//.... 

B* c = new C;     // c is at 0x00a97c78 
A* a = (A*)c;     // a is at 0x00a97c78 (vftable pointer of B) 
A* a1 = dynamic_cast<A*>(c); // a1 is at 0x00a97c7c (vftable pointer of A) 
+0

dotyczy również, dlaczego? podczas owijania wskaźników C++ obiektów w języku C# za pomocą P/Invoke i próbowania kontrolowania wskaźników interfejsu. Wymagana jest dynamiczna obsada od wspólnego typu przodka do interfejsu docelowego. – ceztko

1

Państwo problem zostanie rozwiązany, jeśli używasz dynamicznego oddanych

MyInterface* mInterface = dynamic_cast<MyInterface*>(item); 

This questions oferty różnych C++ odlewane i kiedy je stosować. W twoim przypadku z powodu wielokrotnego dziedziczenia należy używać dynamicznych odlewane

+0

[.........] –

Powiązane problemy