If you know that the conversion works, it doesn't matter, right?
Now that's perfect question to be answered with someone's signature (I really searched for it and couldn't find) which goes something like:
"Although it might be possible to collect the twigs using your nose, it doesn't necessarily mean it's the best way."
I'm assuming you didn't see the problem.
------------------------------------------
Calling free_function() with pb. => Remember pb points to object of type base, which does not implement a function named special_function().
Inside base::some_function()
dynamic_cast returned NULL. pb was NOT pointing to an obj of type derived. => dynamic_cast knows that pb can not and must not be converted to derived*, so it returns NULL.
Doing C-style casting
Inside derived::special_function() => Even though this object does not have this function a call to it is successful. This is only bad-luck.
------------------------------------------
Now if you still doesn't see the problem, let me give you another one:
#include <iostream>
using namespace std;
enum ActionEnum { GET_LAN_STATUS,
SHUTDOWN_LAN
} ;
class employee
{
public:
employee(const string nameStr):name(nameStr) {}
virtual ~employee() {cout << "Inside ~employee()" << endl ;}
virtual void get_status_of_office_LAN() {cout << "get_status_of_office_LAN() by: " << name.c_str() << endl ;}
string getname() { return name ; }
protected:
string name ;
};
class administrator : public employee
{
public:
administrator(const string nameStr):employee(nameStr) {}
~administrator() {cout << "Inside ~administrator()" << endl ;}
void get_status_of_office_LAN() {cout << "get_status_of_office_LAN() by: " << name.c_str() << endl ;}
void shutdown_office_LAN() {cout << "LAN shutdown by: " << name.c_str() << endl ;}
};
void perform_action( employee *pb, ActionEnum action )
{
switch( action )
{
case GET_LAN_STATUS:
{
pb->get_status_of_office_LAN() ;
break ;
}
case SHUTDOWN_LAN:
{
administrator *converted_pd = dynamic_cast< administrator* > ( pb ) ;
if( 0 != converted_pd )
converted_pd->shutdown_office_LAN() ;
else
cout << pb->getname().c_str() << ": does not have required rights to shutdown LAN." << endl ;
cout << endl << "Doing C-style casting" << endl ;
converted_pd = (administrator*) pb ;
if( 0 != converted_pd )
converted_pd->shutdown_office_LAN() ;
else
cout << pb->getname().c_str() << ": does not have required rights to shutdown LAN." << endl ;
}
default: break;
}
}
int main()
{
administrator *pd = new administrator("Some administrator") ;
employee *pb = new employee("NOT an administrator") ;
cout << endl << "Calling perform_action(GET_LAN_STATUS) with pb." << endl ;
perform_action(pb, GET_LAN_STATUS) ;
cout << endl << "Calling perform_action(SHUTDOWN_LAN) with pb." << endl ;
perform_action(pb, SHUTDOWN_LAN) ;
return 0 ;
}
and here is the output:
----------------------------------------------------------
Calling perform_action(GET_LAN_STATUS) with pb.
get_status_of_office_LAN() by: NOT an administrator
Calling perform_action(SHUTDOWN_LAN) with pb.
NOT an administrator: does not have required rights to shutdown LAN.
Doing C-style casting
LAN shutdown by: NOT an administrator
Press ENTER to continue.
----------------------------------------------------------