I have the following class definition:
class IRenderable {
public:
virtual void Render( wxBitmap * ) = 0;
}
class MyClass : public wxWindow, public IRenderable {
public:
/* costructor, destructor etc... */
void RenderBitmap( wxBitmap *bitmap )
{
// code
}
}
where wxWindow and wxBitmap are classes belonging to wxWidgets library (a C++ portable library for writing GUI applications).
I am using Visual C. The following piece of code is wrong:
MyClass *c = new MyClass(...);
wxWindow *w = (wxWindow *)c;
IRenderable *r_page = (IRenderable *)w;
// bitmap is allocate somewhere else
r_page->RenderBitmap( bitmap );
because i get a runtime error:
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.
What's going on?
What i am doing is the following. A third-party library (wxAUI) get pointers to wxWindow in order to manage them. I have sublcassed wxWindow (MyClass) to add some specific code. So, instead of managing wxWindows objects i am using MyClass objects. In some situations, i ask wxAUI to return me the wxWindow pointer of the "current" window, which should be a pointer to MyClass object. I want to call the RenderBitmap() method on those objects, so i need to cast it to IRenderable, but get that run-time error...
I do not have RTTI enable and don't now if this would solve the problem...
The problem is here:
IRenderable *r_page = (IRenderable *)w;
w
doesn't point to an IRenerable
instance. I can see why you'd think it does, but it doesn't.
Avoid inheriting from multiple classes, and google "diamond inheritance" and "virtual inheritance" for better understanding.
Extract from the wikipedia article on the diamond problem:
C++ by default follows each inheritance path separately, so a D object would actually contain two separate A objects, and uses of A's members have to be properly qualified. If the inheritance from A to B and the inheritance from A to C are both marked "virtual" (for example, "class B : virtual public A"), C++ takes special care to only create one A object, and uses of A's members work correctly. If virtual inheritance and nonvirtual inheritance are mixed, there is a single virtual A and a nonvirtual A for each nonvirtual inheritance path to A. Please note that nonvirtual derivation of A in this case will be useless as direct access to any part of class A from class D will practically always end up with compile error.