Alex Rivera | Logout

Does dynamic_cast really work for multiple inheritance?

Asked 2011-08-29T21:53:45.210
11

I wanted to see if it's possible to create "interfaces", inherit them, and then check at runtime if any random class implements that interface. This is what I have:

struct GameObject {
    int x,y;
    std::string name;

    virtual void blah() { };
};

struct Airholder {
   int oxygen;
   int nitrogen;
};

struct Turf : public GameObject, public Airholder {
   Turf() : GameObject() {
      name = "Turf";
   }

   void blah() { };
};

void remove_air(GameObject* o) {
   Airholder* a = dynamic_cast<Airholder*>(o);
   if(!a) return;
   a->oxygen   = 0;
   a->nitrogen = 0;
};

Now, it works. The documentation says that it works, the test example works.. But also, it didn't compile until I added a virtual method to GameObject. The thing is, I really don't know if the feature is intended to be used like that. What made me wonder there is the fact that I have to declare a virtual function for the class I'm checking. But obviously, there is none, the class I'm checking itself has no virtual functions, in fact my whole code has nothing to do with virtual functions, it's an entirely different approach.

So, I guess my question is: If what I'm doing really works, why do I need a virtual function to give my class a vtable? Why can't I declare the class a "runtime type" or something without virtual functions?

Edit
Report

2 Answers

1

As others have said, you need at least one virtual function to make a class polymorphic. Why this matters is that dynamic_cast itself is a polymorphic operation! Given a base class pointer, it returns different results based on the actual object it is called on.

C++ has a "don't pay for what you don't need" philosophy, thus the vtable (or whatever mechanism the compiler uses) is not provided unless there's a need as determined by the presence of a virtual function. Evidently the designers of C++ thought this was a reasonable requirement for the proper operation of dynamic_cast or they would have provided a way to generate a vtable without it.

answered 2011-08-29T22:49:28.553
-2

[EDIT] According to the comments (people way smarter than me) my answer is completely wrong. However, make your destructors virtual anyway. [/EDIT]

In C++, I consider upcasting to a base type is only safe if the destructor is virtual. Technically it's safe, but in reality, you almost always want a virtual destructor. For instance:

class Base {
   int thingy;
};
class Derived : Base{
   int *array;
   Derived() {array = new int[100];}
   ~Derived() {delete [] array;}
};
int main() {
    std::auto_ptr<Base> obj(dynamic_cast<Base*>(new Derived));
}

In this example, when obj goes out of scope, the auto_ptr automatically calls the Base's destructor, but does not call the Derived deconstructor because the type is a Base, not a Derived. [Edit: corrections] This causes Undefined behaviour (at the very best, it causes a memory leak). I haven't any idea why C++ doesn't require a virtual destructor to compile down casts, it really should.

answered 2011-08-29T22:04:12.823

Your Answer