I read in a C++ book that you can use dynamic_cast to downcast a pointer to a base object to a derived object pointer, if the object it points to actually is that of the derived type. The format is dynamic_cast<Derived*>(basePointer)
. Furthermore, I read on this website that dynamic_cast should return a null pointer if the object it points to cannot be converted to the derived class type.
However, I recently tried having a pointer to a plain object with a virtual function downcast to an object that's derived from a different class, in order to call one of that class' functions. To my surprise, it worked:
#include <iostream>
using namespace std;
class Object {
public:
virtual ~Object () {}
};
class Base {
public:
virtual void doSomething () {
cout << "Done something!" << endl;
}
};
class Derived: public Base {
public:
virtual void doSomething () {
cout << "You done goofed!" << endl;
}
void printFoo () {
cout << "Foo" << endl;
}
private:
int x;
};
int main () {
Object o;
Object* p = &o;
if(dynamic_cast<Derived*>(p))
cout << "Yep, baby is derived!" << endl;
else
cout << "Isn't derived." << endl;
dynamic_cast<Derived*>(p)->printFoo();
return 0;
}
Here, Base is a base class type designed to be used polymorphically (that is, it contains a virtual function), and Derived is a class type derived from Base. Object is just a plain class that is not related to either class, but its destructor is made virtual so that it can be used polymorphically. I'll explain the purpose of Derived::x in a moment. In the main function, an Object is created and a pointer to Object is assigned to its address. It checks whether Derived is a descendant of that pointer, and prints whether it is or it isn't. Then it casts that pointer to a pointer of type Derived, and Derived's printFoo function is called.
This shouldn't work, but it does. When I run it, it displays "Isn't derived," so it clearly understands that Obect is not Derived from Base, but then it prints "Foo" on the screen and exits without error. However, if I add the line x = 1;
to the printFoo function, it exits with a Segmentation fault, as it's trying to assign a variable which doesn't exist in that object. Furthermore, this only seems to work with non-virtual functions. If I try to call the virtual function doSomething, for instance, I get the Segmentation fault before "You done goofed!" is ever printed out.
What's going on here? Shouldn't dynamic_cast<Derived*>(p)
return a null pointer, so that trying to call printFoo from that would automatically cause an error? Why is that working when it shouldn't?
NULL
pointer doesn't automatically cause an error, you'll have to check before calling. – πάντα ῥεῖ