I'm having a bit of trouble with dynamic_casting. I need to determine at runtime the type of an object. Here is a demo:
#include <iostream>
#include <string>
class PersonClass
{
public:
std::string Name;
virtual void test(){}; //it is annoying that this has to be here...
};
class LawyerClass : public PersonClass
{
public:
void GoToCourt(){};
};
class DoctorClass : public PersonClass
{
public:
void GoToSurgery(){};
};
int main(int argc, char *argv[])
{
PersonClass* person = new PersonClass;
if(true)
{
person = dynamic_cast<LawyerClass*>(person);
}
else
{
person = dynamic_cast<DoctorClass*>(person);
}
person->GoToCourt();
return 0;
}
I would like to do the above. The only legal way I found to do it is to define all of the objects before hand:
PersonClass* person = new PersonClass;
LawyerClass* lawyer;
DoctorClass* doctor;
if(true)
{
lawyer = dynamic_cast<LawyerClass*>(person);
}
else
{
doctor = dynamic_cast<DoctorClass*>(person);
}
if(true)
{
lawyer->GoToCourt();
}
The main problem with this (besides having to define a bunch of objects that won't be use) is that I have to change the name of the 'person' variable. Is there a better way?
(I am not allowed to change any of the classes (Person, Lawyer, or Doctor) because they are part of a library that people who will use my code have and won't want to change).
Thanks,
Dave
Dynamic casting to a subclass and then assigning the result to a pointer to superclass is of no use - you practically are back where you started. You do need a pointer to a subclass to store the result of the dynamic cast. Also, if the concrete type of your object is PersonClass
, you can't downcast it to a subclass. Dynamic casting can only work for you if you have a pointer to a superclass but you know that the object pointed to is actually an instance of a subclass.
As others have pointed out too, the best option would be to redesign the class hierarchy to make your methods really polymorphic, thus eliminate the need for downcasting. Since you can't touch those classes, you need the downcast. The typical way to use this would be something like
PersonClass* person = // get a Person reference somehow
if(/* person is instance of LawyerClass */)
{
LawyerClass* lawyer = dynamic_cast<LawyerClass*>(person);
lawyer->GoToCourt();
}
else
{
DoctorClass* doctor = dynamic_cast<DoctorClass*>(person);
doctor->GoToSurgery();
}
Update: if you want to use the subclass instances later, you can do it this way:
PersonClass* person = // get a Person reference somehow
...
LawyerClass* lawyer = NULL;
DoctorClass* doctor = NULL;
if(/* person is instance of LawyerClass */)
{
lawyer = dynamic_cast<LawyerClass*>(person);
}
else if(/* person is instance of DoctorClass */)
{
doctor = dynamic_cast<DoctorClass*>(person);
}
...
if(lawyer)
{
lawyer->GoToCourt();
}
else if (doctor)
{
doctor->GoToSurgery();
}
Note that this code is more complicated and more error-prone than the previous version. I would definitely try to refactor such code to make it look more like the previous version. YMMV.