c++castingdynamic-castdowncastupcasting

C++ derived-class members after downcasting


I recently learned about upcasting and downcasting in C++. However I came up with a few questions during reading about downcasting. Say I have two classes

class Base {
  public:
    virtual void foo() {}
};

class Derived : public Base {
  public:
    Derived(int i) {
        mem = i;
    }
    int mem;
};

My questions are the followings:

  1. If I create an object Derived d(1), upcast to Base class, and then downcast it back to Derived class, is 'mem==1' preserved? Do I still have access to it? Assume pointer or reference is used so object slicing doesn't happen and dynamic_cast is used for downcasting.
  2. When downcasting from Base class to Derived class, there will an additional member variable 'mem'. Is memory allocated for 'mem' during run-time (using dynamic_cast)? To what value will it be initialized to?

After some simple experiments, 1 seems to be true.

However for 2 it seems I can't start from a Base class pointer and dynamic_cast it into Derived class pointer as dynamic_cast returns null.

I read from another post saying "But the basic point of dynamic_cast is that it first checks that the pointee object is really of the derived type, and then returns a pointer to it, or returns a null pointer if the pointee object isn't actually of (or derived from) the requested target type."

Is this saying we can't actually start from the Base class and simply downcast it into Derived class, but rather the whole point of dynamic_cast is to "cast back" something that has been upcasted?


Solution

    1. It depends; if you cast a Derived object to Base, the result is a new object created by omitting the fields that are not in the Base. However, if you cast a pointer to Derived (i.e. Derived*), the result is a pointer which points to the same object but whose type is Base*.

    2. It depends; if you cast a Base object, you get a compile error unless you overload the typecast operator for doing such an operation (you have correctly observed that the values of the fields would otherwise be undefined). However, if you cast a Base* (a pointer) to Derived* (using dynamic_cast<Derived*>(p)), the result depends on the object the pointer points to. If it points to an instance of the Derived class (or its subclass), the result is a Derived* pointer to that object; otherwise, you get a nullptr pointer of type Derived*.