在c ++中调用虚方法会导致访问冲突

时间:2018-02-17 12:58:31

标签: c++ polymorphism access-violation

我有一个名为Renderable的类,其中包含一个纯虚方法draw()

class Renderable : public QOpenGLFunctions
{
public:
   virtual void draw() = 0;
}

我有一个继承自Renderable的类GeomObject,也可以从Transformable继承(Transformable是一个普通的类,而不是虚拟的)

class GeomObject : public Renderable, public Transformable

GeomObject重载draw()方法。 另外,我有一个Scene类,我想要循环场景对象,如果它们是可渲染的,则绘制它们。它们中的每一个都具有isRenderable bool变量,该变量设置为true。在这种情况下,所有这些对象都是GeomObjects。这里的SceneObject是一个常规类(非虚拟)

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 Renderable : public QOpenGLFunctions 
class SceneObject 
class Transformable : public SceneObject 
class GeomObject : public Renderable, public Transformable

类层次结构的可验证示例(它可以工作,因此问题可能在其他地方)

#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;
}

1 个答案:

答案 0 :(得分:1)

工作示例不是您描述的问题的有效示例。在您的问题中,您尝试将SceneObject*投射到Renderable*。在工作示例中,您将GeomObject*投射到Renderable*。与SceneObject相比,Renderable位于继承链中的另一个分支上,我无法直接将对象转换为另一个分支。

如果您绝对想要在非工作示例中使用Renderable*,则应首先转换为GeomObject*,然后转换为Renderable*

另外,正如已经指出的那样:使用static_castdynamic_cast代替C风格演员。