我有以下类定义:
class IRenderable {
public:
virtual void Render( wxBitmap * ) = 0;
}
class MyClass : public wxWindow, public IRenderable {
public:
/* costructor, destructor etc... */
void RenderBitmap( wxBitmap *bitmap )
{
// code
}
}
其中wxWindow和wxBitmap是属于wxWidgets库的类(用于编写GUI应用程序的C ++可移植库)。
我正在使用Visual C.以下代码错误:
MyClass *c = new MyClass(...);
wxWindow *w = (wxWindow *)c;
IRenderable *r_page = (IRenderable *)w;
// bitmap is allocate somewhere else
r_page->RenderBitmap( bitmap );
因为我收到运行时错误:
运行时检查失败#0 - 未正确保存ESP的值 跨函数调用。这通常是调用a的结果 用一个带有函数指针的调用约定声明的函数 用不同的调用约定声明。
发生了什么事?
我正在做的是以下内容。第三方库(wxAUI)获取指向wxWindow的指针以便管理它们。我已经sublcassed wxWindow(MyClass)添加一些特定的代码。因此,我使用的是MyClass对象,而不是管理wxWindows对象。 在某些情况下,我要求wxAUI返回“当前”窗口的wxWindow指针,该指针应该是指向MyClass对象的指针。我想在这些对象上调用RenderBitmap()方法,所以我需要将它转换为IRenderable,但是得到运行时错误......
我没有启用RTTI,如果这样可以解决问题,现在就不行了......
答案 0 :(得分:1)
问题在于:
IRenderable *r_page = (IRenderable *)w;
w
未指向IRenerable
个实例。我明白为什么你会这么认为,但事实并非如此。
避免从多个类继承,并谷歌“钻石继承”和“虚拟继承”以便更好地理解。
从钻石问题的wikipedia article中摘录:
默认情况下,C ++分别跟随每个继承路径,因此是D对象 实际上会包含两个单独的A对象,以及A成员的使用 必须得到适当的资格。如果继承从A到B和 从A到C的继承都标记为“虚拟”(例如,“class” B:虚拟公共A“),C ++特别注意只创建一个A. 对象和A成员的使用正常工作。如果虚拟继承 和非虚拟继承是混合的,有一个虚拟的A和 A的每个非虚拟继承路径的非虚拟A。请注意 在这种情况下,A的非虚拟推导将是无用的直接 从D类访问A类的任何部分几乎总是会结束 编译错误。