Some say the use of dynamic_cast often means bad design and dynamic_cast can be replaced by virtual functions
dynamic_cast
considered bad design?Suppose I have I function name func(Animal* animal, int animalType)
, the implementation in func is like:
bool func(Animal* animal, int animalType)
{
...
/* Animal is the base class of Bear, Panda, Fish ....
dynamic_cast animal to real animals(Bear, Panda, Fish...)
according to animalType. Do some processing with this specific
type of animal, using its additional information beyond base
class Animal. */
}
Is this case a proper use of dynamic_cast
?
This cast is used for handling polymorphism. You only need to use it when you're casting to a derived class. This is exclusively to be used in inheritence when you cast from base class to derived class.
The primary purpose for the dynamic_cast operator is to perform type-safe downcasts. A downcast is the conversion of a pointer or reference to a class A to a pointer or reference to a class B , where class A is a base class of B .
Yes, dynamic_cast is a code smell, but so is adding functions that try to make it look like you have a good polymorphic interface but are actually equal to a dynamic_cast i.e. stuff like can_put_on_board .
While typeid + static_cast is faster than dynamic_cast , not having to switch on the runtime type of the object is faster than any of them. Save this answer.
This is EXACTLY the wrong place to use dynamic_cast
. You should be using polymorphism. Each of the Animal
classes should have a virtual
function, say, process
and here you should just call animal->process()
.
class Animal {
virtual void Process() = 0;
}
class Cat : public Animal {
void Process() { std::cout << " I am a tiny cat"; }
}
class Bear : public Animal {
void Process() { std::cout << "I am a big bear"; }
}
void func(Animal * animal) {
if (animal != nullptr) { animal->Process(); }
}
Other problems.
What if animal
is a Dog
, but due to a bug animal_type
says its a Cat
?
There are times when static_cast
is necessary, and if possible use it instead of dynamic_cast
. Dynamic cast has the additional performance cost that static cast does not. For this, you need to be sure you know the type that is coming in, since static_cast
is more unsafe.
At the very least, animal_type
should be a member of Animal
.
In theory, down-casting should never be necessary. Instead you should adapt the base class to include the necessary virtual
method.
In practice, you encounter things such as 3rd party libraries. In this case, modifying the base class is not an option and thus you may be forced into using dynamic_cast
...
Back to your example:
class Animal {
public:
// starts moving toward `p`,
// throws a `Unreachable` exception if `p` cannot be reached at the moment.
virtual void moveToward(Point const& p) = 0;
}; // class Animal
And then:
bool move(Animal& animal, Point const& p) {
try {
animal.moveToward(p);
return true;
} catch (Unreachable const& e) {
LOG(animal.id() << " cannot reach " << p << ": " << e.what());
}
return false;
} // move
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With