在 C++ 中调用虚拟方法会导致访问冲突
Calling virtual method in c++ gives access violation
我有一个名为 Renderable 的 class,带有一个纯虚方法 draw()
class Renderable : public QOpenGLFunctions
{
public:
virtual void draw() = 0;
}
我有一个 class 继承自 Renderable 和 Transformable 的 GeomObject(Transformable 是常规的 class,不是虚拟的)
class GeomObject : public Renderable, public Transformable
GeomObject 重载了 draw() 方法。
另外,我有一个场景 class,我想在其中循环场景对象,如果它们是可渲染的,则绘制它们。它们每个都有设置为 true 的 isRenderable bool 变量。在这种情况下,所有这些对象都是 GeomObjects。这里的SceneObject是常规的class(不是虚拟的)
for ( unsigned int i = 0; i < this->sceneObjects.count(); i++ ) {
SceneObject* obj = this->sceneObjects[i];
if ( obj->isRenderable ) {
( ( Renderable* )obj )->draw(); //access violation
}
}
这是我遇到访问冲突的地方。但是如果我直接转换为 GeomObject* 然后调用 draw(),一切正常。
for ( unsigned int i = 0; i < this->sceneObjects.count(); i++ ) {
SceneObject* obj = this->sceneObjects[i];
if ( obj->isRenderable ) {
( ( GeomObject* )obj )->draw(); // this works
}
}
我做错了什么?
这是我的 class 层次结构:
class Renderable : public QOpenGLFunctions
class SceneObject
class Transformable : public SceneObject
class GeomObject : public Renderable, public Transformable
class 层次结构的可验证示例(有效,所以问题可能出在其他地方)
#include <iostream>
using namespace std;
class QOpenGLFunctions
{};
class Renderable : public QOpenGLFunctions
{
public:
virtual void draw() = 0;
};
class SceneObject
{};
class Transformable : public SceneObject
{};
class GeomObject : public Renderable, public SceneObject
{
public:
void draw(){
cout << "Draw() is called";
}
};
int main() {
GeomObject * obj = new GeomObject();
((Renderable*)obj)->draw();
return 0;
}
工作示例不是您描述的问题的有效示例。在您的问题中,您尝试将 SceneObject*
转换为 Renderable*
。在工作示例中,您将 GeomObject*
转换为 Renderable*
。与 Renderable
相比,SceneObject
位于继承链中的不同分支,我不知道如何将对象直接转换为另一个分支。
如果您绝对想在 non-working 示例中使用 Renderable*
,您应该能够先转换为 GeomObject*
,然后再转换为 Renderable*
。
此外,正如已经指出的那样:使用 static_cast
或 dynamic_cast
而不是 C-style 强制转换。
我有一个名为 Renderable 的 class,带有一个纯虚方法 draw()
class Renderable : public QOpenGLFunctions
{
public:
virtual void draw() = 0;
}
我有一个 class 继承自 Renderable 和 Transformable 的 GeomObject(Transformable 是常规的 class,不是虚拟的)
class GeomObject : public Renderable, public Transformable
GeomObject 重载了 draw() 方法。 另外,我有一个场景 class,我想在其中循环场景对象,如果它们是可渲染的,则绘制它们。它们每个都有设置为 true 的 isRenderable bool 变量。在这种情况下,所有这些对象都是 GeomObjects。这里的SceneObject是常规的class(不是虚拟的)
for ( unsigned int i = 0; i < this->sceneObjects.count(); i++ ) {
SceneObject* obj = this->sceneObjects[i];
if ( obj->isRenderable ) {
( ( Renderable* )obj )->draw(); //access violation
}
}
这是我遇到访问冲突的地方。但是如果我直接转换为 GeomObject* 然后调用 draw(),一切正常。
for ( unsigned int i = 0; i < this->sceneObjects.count(); i++ ) {
SceneObject* obj = this->sceneObjects[i];
if ( obj->isRenderable ) {
( ( GeomObject* )obj )->draw(); // this works
}
}
我做错了什么?
这是我的 class 层次结构:
class Renderable : public QOpenGLFunctions
class SceneObject
class Transformable : public SceneObject
class GeomObject : public Renderable, public Transformable
class 层次结构的可验证示例(有效,所以问题可能出在其他地方)
#include <iostream>
using namespace std;
class QOpenGLFunctions
{};
class Renderable : public QOpenGLFunctions
{
public:
virtual void draw() = 0;
};
class SceneObject
{};
class Transformable : public SceneObject
{};
class GeomObject : public Renderable, public SceneObject
{
public:
void draw(){
cout << "Draw() is called";
}
};
int main() {
GeomObject * obj = new GeomObject();
((Renderable*)obj)->draw();
return 0;
}
工作示例不是您描述的问题的有效示例。在您的问题中,您尝试将 SceneObject*
转换为 Renderable*
。在工作示例中,您将 GeomObject*
转换为 Renderable*
。与 Renderable
相比,SceneObject
位于继承链中的不同分支,我不知道如何将对象直接转换为另一个分支。
如果您绝对想在 non-working 示例中使用 Renderable*
,您应该能够先转换为 GeomObject*
,然后再转换为 Renderable*
。
此外,正如已经指出的那样:使用 static_cast
或 dynamic_cast
而不是 C-style 强制转换。