4

I'v asked these question some time ago: Multiple inheritance casting from base class to different derived class

But I'm still not sure I understand the answer. The question is: Is the code below valid?

#include <iostream>

using namespace std;

struct Base
{
    virtual void printName() 
    {
        cout << "Base" << endl;
    }
};

struct Interface
{
    virtual void foo()
    {
        cout << "Foo function" << endl;
    }
};

struct Derived : public Base, public Interface
{
    virtual void printName()
    {
        cout << "Derived" << endl;
    }
};

int main(int argc, const char * argv[])
{
    Base *b = new Derived();
    Interface *i = dynamic_cast<Interface*>(b);
    i->foo();

    return 0;
}

The code works as I want. But as I understand, according to previous question, it should not. So I'm not sure if such code is valid. Thanks!

Community
  • 1
  • 1
Andrew
  • 24,218
  • 13
  • 61
  • 90
  • The comments in the answer(s) to your previous question do explain that `dynamic_cast` will work in your case. – Chad May 01 '12 at 16:36

5 Answers5

5

It is valid code.

Why?
Because dynamic_cast tells you if the object being pointed to is actually of the type you are casting to.
In this case the actual object being pointed to is of the type Derived and each object of the type Derived is also of the type Interface(Since Derived inherits from Interface) and hence the dynamic_cast is valid and it works.

Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • What's the difference with my previous question? (really can't understand) – Andrew May 01 '12 at 16:40
  • @Andrew: There's no difference, Emilio Garavaglia gave you the same answer in the previous question. – interjay May 01 '12 at 16:41
  • 2
    @Andrew: `dynamic_cast` only works if you have atleast one `virtual` method in the class(aka polymorphic classes).See [this](http://stackoverflow.com/questions/4227328/faq-why-does-dynamic-cast-only-work-if-a-class-has-at-least-1-virtual-method).Your prior example didn't have any `virtual` method and hence `dynamic_cast` could not be used. – Alok Save May 01 '12 at 16:42
  • Do I understand correct that all classes involved in dynamic_cast must be polymorphic ? – Andrew May 01 '12 at 16:44
  • @Andrew: Yes. And if the base class is polymorphic all derived classes will be polymorphic too.You just need one `virtual` method in the Base class and it could even be a destructor. – Alok Save May 01 '12 at 16:45
3

As long as the classes involved have at least one virtual method (which could be a virtual destructor), using dynamic_cast as you are is both correct and will work on a conforming compiler.

Unlike static_cast, dynamic_cast can allow runtime checking of type information. However, this also means that it can fail, and return a NULL when using it to cast pointers. The cast result should be checked if there is any chance it might not succeed.

In the previous question you asked, the classes did not have any virtual methods, and as such, would not work, since dynamic_cast cannot be used on such a class.

Dave S
  • 20,507
  • 3
  • 48
  • 68
0

If dynamic_cast succeed then it is valid. It already perform a type safety check at runtime.

UmNyobe
  • 22,539
  • 9
  • 61
  • 90
  • While that happens to be true in this case, I don't like to set the precedent that "if it works, it's correct.". – Chad May 01 '12 at 16:37
  • well because it is `dynamic_cast`, that's the argument. I don't want to reexplain what appears in more than 10 well known questions on SO – UmNyobe May 01 '12 at 16:39
  • @UmNyobe: The problem OP had is *why it works?* the answer to that is not because `dynamic_cast` says so. He already knows that `dynamic_cast` says so(OP put up an well made example code to demonstrate it) the real q is *Why `dynamic_cast` works?* – Alok Save May 01 '12 at 16:49
0

Consider the following:

Base *b = new B();
Interface *i = dynamic_cast<Interface *>( b );

Should this work? No. Why, because Base and Interface are not related to each other. However, in the special case where a pointer to Base is pointing to an object which is also derived from Interface you can cast (read: coax the compiler into considering the object to be of type Interface) the Base pointer and use the result of the dynamic_cast operator further.

dirkgently
  • 108,024
  • 16
  • 131
  • 187
0

Your code is valid because the standard says so in 5.2.7 paragraph 4 (C++ 2003 standard):

The run-time check logically executes as follows:

— If, in the most derived object pointed (referred) to by v, v points (refers) to a public base class sub- object of a T object, and if only one object of type T is derived from the sub-object pointed (referred) to by v, the result is a pointer (an lvalue referring) to that T object.

— Otherwise, if v points (refers) to a public base class sub-object of the most derived object, and the type of the most derived object has a base class, of type T, that is unambiguous and public, the result is a pointer (an lvalue referring) to the T sub-object of the most derived object.

— Otherwise, the run-time check fails.

Note the use of "most derived object" in the run-time checks. In your example, the "most derived object" for your Base *b object is a Derived object. Since class Derived inherits publicly from both Base and Interface, that Base* object can be cast to a Interface* in this particular case.

Community
  • 1
  • 1
David Hammen
  • 32,454
  • 9
  • 60
  • 108