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:
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.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?
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*
.
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*
.