-1

I have two classes, base class and a derived class. The base class has a virtual method.

Here is my test example:

class Base
{
public:
    virtual void Hello() { cout << "-> Hello Base" << endl; }
};

class Derived: public Base
{
public:
    void Hello() { cout << "-> Hello Derived" << endl; }
};

int main()
{
    Base *mBase = new Base;
    // something to do 
    ....

    Derived *mDerived = dynamic_cast<Derived*>(mBase);
    mDerived->Hello();

    return 0;
}

I'm looking to use the Hello() method of the class derived after the cast of mBase to mDerived.

But the problem is that when I try to use dynamic_cast it will crash the application, if not if I use reinterpret_cast the Hello() method of the Base class will be called.

Result in the case dynamic_cast:

Segmentation fault (core dumped)

Result in the case dynamic_cast:

-> Hello Base
Jean-Baptiste Yunès
  • 34,548
  • 4
  • 48
  • 69
adir
  • 15
  • 6
  • `Base *mBase = new Base;` should be `Base *mBase = new Derived;` – Alan Birtles May 06 '20 at 10:03
  • 1
    You create a `Base` object and try to cast it to a `Derived` that cannot work – 463035818_is_not_an_ai May 06 '20 at 10:03
  • `dynamic_cast(mBase);` will return null pointer because `mBase` does not point at `Base` subobject of `Derived` object, so you dereference invalid pointer. Use of pointer returned by `reinterpret_cast` will be undefined behavior as well for the same reason - `mBase` does not point at `Base` subobject of `Derived` object. – user7860670 May 06 '20 at 10:13
  • Are you expecting casting to change the type of the object? It doesn't. – molbdnilo May 06 '20 at 10:13

2 Answers2

3

dynamic_cast fails when cast a base class to derived class

This is what is supposed to happen. When you dynamic cast a pointer to an object whose dynamic type is not the casted type, then you get a null pointer as the result.

In your example, you indirect through the null pointer and attempt to call a member function which results in undefined behaviour.

When using dynamic cast, you must always check whether you got null or not.

if I use reinterpret_cast...

Then the behaviour will still be undefined because you'll be indirecting through a pointer to an object that does not exist. Unless you create an instance of the derived class, you cannot call its non static member function.

You can convert a base instance into a derived one like this for example:

Base b;
Derived d = b;

What happens is that the base sub object of the derived instance is copy initialised from b.

eerorika
  • 232,697
  • 12
  • 197
  • 326
0

Two problems in your code: Base should have a virtual destructor so Dervied isntances can be properly destructed via a pointer to Base. Then, you are not constructing an object of type Derived, so the cast cannot succeed. dynamic_cast can fail and you should check its result for not being a nullptr. Also you forgot to delete the created object.

If you do create an instance of type Derived your code works:

#include <iostream>
using std::cout;
using std::endl;

class Base
{
public:
    virtual void Hello() { cout << "-> Hello Base" << endl; }
    virtual ~Base(){}
};

class Derived: public Base
{
public:
    void Hello() { cout << "-> Hello Derived" << endl; }
};

int main()
{
    Base* mBase = new Derived;
    Derived *mDerived = dynamic_cast<Derived*>(mBase);
    if (mDerived) mDerived->Hello();
    delete mBase;
}
463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
  • 1
    virtual destructor is not mandatory to be a polymorphic type, at least one virtual method or constructor is. – Jean-Baptiste Yunès May 06 '20 at 10:16
  • @Jean-BaptisteYunès There is no such thing as virtual constructor. While it may not technically be required for the class to be polymorphic, the virtual destructor is absolutely necessary for `delete mBase;` to have well defined behaviour however. – eerorika May 06 '20 at 10:19
  • @Jean-BaptisteYunès changed the wording (and fixed the leak) – 463035818_is_not_an_ai May 06 '20 at 10:49
  • @eerorika would have write destructor, sorry. "the virtual destructor is absolutely necessary" no certainly not. In most of the case yes, but there exists cases were it is not necessary (think about hierarchy of classes without fields for example). I know it is a recommandation, but it is not **necessary**. – Jean-Baptiste Yunès May 06 '20 at 12:32
  • @Jean-BaptisteYunès Whether the classes have fields or not is irrelevant. The behaviour of deleting a pointer which points to a base sub object is always undefined unless the destructor of that base is virtual in C++. – eerorika May 06 '20 at 12:37
  • @eerorika seriously. Any reference? I'm interested in. – Jean-Baptiste Yunès May 06 '20 at 12:38
  • 1
    @Jean-BaptisteYunès See the standard section [expr.delete] – eerorika May 06 '20 at 12:39
  • @eerorika Right! Thanks! I've never read/noticed that before... – Jean-Baptiste Yunès May 06 '20 at 12:46