-1

I have a class named Renderable with one pure virtual method draw()

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

And I have a class GeomObject that inherits from Renderable and also from Transformable (Transformable is a regular class, not virtual)

class GeomObject : public Renderable, public Transformable

GeomObject overloads draw() method. Also, I have a Scene class, in which I want cycle trough scene objects, and if they are Renderable, draw them. Each of them have isRenderable bool variable which is set to true. In this case, all of these objects are GeomObjects. SceneObject here is a regular class (not virtual)

for ( unsigned int i = 0; i < this->sceneObjects.count(); i++ ) {
    SceneObject* obj = this->sceneObjects[i];
    if ( obj->isRenderable ) {          
        ( ( Renderable* )obj )->draw(); //access violation
    }
} 

This is where I get access violation. But if I cast directly to GeomObject* and then call draw(), everything works fine.

for ( unsigned int i = 0; i < this->sceneObjects.count(); i++ ) {
    SceneObject* obj = this->sceneObjects[i];
    if ( obj->isRenderable ) {          
        ( ( GeomObject* )obj )->draw(); // this works
    }
} 

What am I doing wrong?

Here is my class hierarchy:

class Renderable : public QOpenGLFunctions 
class SceneObject 
class Transformable : public SceneObject 
class GeomObject : public Renderable, public Transformable

Verifiable example of class hierarchy (it works, so the problem is probably somewhere else)

#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;
}
3dmodels
  • 103
  • 7
  • 4
    Note: The usage of a C-style cast almost certainly shuts up your compiler's warnings. Use the appropriate explicit C++ casts. In your case of multiple inheritance, use `dynamic_cast` and check that the returned pointer is valid before making a call on it – WhiZTiM Feb 17 '18 at 13:04
  • 2
    Don't use C-style casts, in particular when there is multiple inheritance involved. Use `dynamic_cast`, or `static_cast` if you're certain of the type. – molbdnilo Feb 17 '18 at 13:05
  • 2
    There seems to be no connection between `SceneObject` class and `Renderable` class for cast of any kind to make sense. – user7860670 Feb 17 '18 at 13:06
  • 5
    Post a **complete example** that a reader can copy, paste and compile without modification. – Cheers and hth. - Alf Feb 17 '18 at 13:10
  • 1
    @Ron It's casting a pointer, which would be fine if it were the proper kind of cast. – molbdnilo Feb 17 '18 at 13:14
  • 2
    _GeomObject overloads draw() method_ https://stackoverflow.com/a/429236/8746007 – Killzone Kid Feb 17 '18 at 13:24
  • SceneObject is a regular class, not virtual. – 3dmodels Feb 17 '18 at 13:37
  • 2
    But what is the relationship of `SceneObject` to `GeomObject`, `Renderable` and/or `Transformable`? Please show the class definition for `SceneObject`. – G.M. Feb 17 '18 at 13:48
  • 1
  • I'll try to make complete example a bit later. Here is my class hierarchy: class Renderable : public QOpenGLFunctions class SceneObject class Transformable : public SceneObject class GeomObject : public Renderable, public Transformable – 3dmodels Feb 17 '18 at 14:17
  • 1
    @molbdnilo Indeed. I stand corrected. – Ron Feb 17 '18 at 14:17
  • Added a copy-pastable examble (edited the original post) – 3dmodels Feb 17 '18 at 14:49
  • Compile with all warnings and debug info: `g++ -Wall -Wextra -g` with [GCC](http://gcc.gnu.org/). Then [use the `gdb` debugger](https://sourceware.org/gdb/current/onlinedocs/gdb/). And don't comment your own question, but edit it to improve it – Basile Starynkevitch Feb 17 '18 at 14:58

1 Answers1

1

The working example is not a valid example of the problem you describe. In your problem you try to cast a SceneObject* to a Renderable*. In the working example you are casting a GeomObject* to a Renderable*. SceneObject lies on a different branch in the inheritance chain compared to Renderable and there is no way I know of to directly cast an object to another branch.

If you absolutely want to use the Renderable* in your non-working example, you should be able to first cast to GeomObject* and then to Renderable*.

Also, as has been pointed out: Use static_cast or dynamic_cast instead of C-style cast.

marcks
  • 400
  • 1
  • 2
  • 11