Reputation: 816
Let's suppose I have two classes mapping two objects that have the same interface
class FirstChild : class Father
{
//some fields and methods useful for class A
}
class SecondChild : class Father
{
//some fields and methods useful for class B
}
Later, in the code something like that is done
Father* myInstance = new SecondChild();
Now, if I want to know the type
of the object such that some operation must be done if the instance is a FirstChild or SecondChild I'm doing something like that:
if (typeid (myInstance) == typeid (FirstChild))
{
// do stuff
} else if (typeid (myInstance) == typeid (SecondChild))
{
// do other stuff
}
Is this the correct way of doing that?
Because somewhere on StackOverflow
I read that typeid
is not safe and it's more convenient to add a virtual function, let's say getType
for example, and do, in FirstChild
char* getType { return "FirstChild"; }
To be honest, I don't like this solution too much because it seems that we bypass the poweful of the polymorphism in the Object-Oriented Programming.
So, you guys, what do you think? What's the best way to check the type of a child-object in c++?
Upvotes: 0
Views: 108
Reputation: 596
One easy way to do this uses dynamic_cast
. Example:
Father *myInstance = new SecondChild();
SecondChild *casted = dynamic_cast<SecondChild*>(myInstance);
if (casted != nullptr)
std::cout << "myInstance is a SecondChild!";
else
std::cout << "myInstance is not a SecondChild!";
From: cppreference: dynamic cast
If the cast is successful, dynamic_cast returns a value of type new_type. If the cast fails and new_type is a pointer type, it returns a null pointer of that type. If the cast fails and new_type is a reference type, it throws an exception that matches a handler of type std::bad_cast.
As @Rob has pointed out, you can use a virtual function and let the object do the action itself.
struct Father
{
virtual void process() = 0;
};
You could use a virtual function to decide whether the action should be done, rather than checking the type.
struct Father
{
virtual bool shouldProcess() { return false; }
};
struct SecondChild : Father
{
bool shouldProcess() override { return true; }
}
Upvotes: 0
Reputation: 2014
There are a couple of ways to do this.
typeid
and dynamic_cast<>
are the "official ways" to do that.
FirstChild *fptr = dynamic_cast<FirstChild>(myInstance);
if (fptr) {
// do something
} else {
SecondChild *cptr = dynamic_cast<SecondChild>(myInstance);
if(cptr) {
// do something else, and so on...
}
}
But this is not the most elegant way to do this.
Another equivalent way is to have an "id type", like an enum or similar.
But as many said, if you need to know what the type is, you're probably doing it the wrong way.
An obvious alternative is to let the object do the specific action. Suppose you are using this code in a activate()
function. Why not using a virtual doAction()
?
class Father {
public:
virtual void doAction() = 0;
}
//...
myInstance->doAction();
There are variation of this, using different design pattern. But I guess you got the point.
Upvotes: 1