Downcasting is defined as casting a pointer or reference of a base class type to a type of a pointer or reference to a derived class.
Mostly used to restore the object to its original type.
Downcasting can lead to trouble due to contravariance, e.g.:
struct Base {
int i_;
virtual int foo (void) { return i_; }
};
struct Derived : public Base {
int j_;
virtual int foo (void) { return j_; }
};
void foo (void) {
Base b;
Derived d;
Base *bp = &d; // "OK", a Derived is a Base
Derived *dp = &b;// Error, a Base is not necessarily a Derived
}
Problem: what happens if dp->j_ is referenced or set?
Since a Derived object always has a Base part certain operations
are ok:
bp = &d;
bp->i_ = 10;
bp->foo (); // calls Derived::foo ();
Since base objects don’t have subclass data some operations aren’t
ok
– e.g., accesses information beyond end of b:
dp = (Derived *) &b;
dp->j_ = 20; // big trouble!
C++ permits contravariance if the programmer explicitly casts, e.g.,
dp = (Derived *) &b; // unchecked cast
RTTI can be used to check the type of the object
if (Derived *dp = dynamic_cast
/* use dp */;
else
/* error! */
For a dynamic cast to succeed, the “actual type” of b would have to
either be a Derived object or some subclass of Derived
dynamic_cast throw bad_cast exception in case of failure
if the types do not match the operation fails at run-time
I had a tough time to understand this feature.. Your post convinced me to the best.
ReplyDeleteThanks,