Explain Codes LogoExplain Codes Logo

C++ equivalent of java's instanceof

c++
type-checking
performance-considerations
compile-time-checks
Nikita BarsukovbyNikita Barsukov·Jan 17, 2025
TLDR

In the C++ universe, dynamic_cast fulfills a similar duty to instanceof in Java:

if (auto* derivedPtr = dynamic_cast<Derived*>(basePtr)) { // Alright! basePtr was actually a cool guy named Derived }

Here, derivedPtr will happily take on a valid form if basePtr turns out to be a Derived object in disguise. Otherwise, derivedPtr sulks and becomes nullptr.

When to skip dynamic_cast (and code cleverly!)

Overuse of dynamic_cast is like lady perfume - a little attracts, too much distracts! It can be a red flag signaling the violation of the Liskov Substitution Principle. Consider using virtual functions to carry out your deeds before resorting to dynamic_cast. Virtual functions are like the James Bond of type checking - sleek, swift, flexible!

Checking out family relations at compile-time

Want to run a family background check? Use std::is_base_of. This template-based approach is your friend during compile-time, giving you insight about inheritance relationships at the cost of exactly zero run-time overhead.

Visitor pattern: A handy replacement strategy

Ever considered faking your identity? Well, objects in code sometimes do too! Implement the Visitor pattern to neatly introduce behaviors in this scenario, avoiding reliance on dynamic_cast. This keeps your codes' identity crisis well organized.

Calling in the twins: dynamic_cast & typeid

typeid can be a good wingman to dynamic_cast; however, it only checks the exact type and is more restricted. On the bright side, it can handle even non-polymorphic entities.

#include <typeinfo> if (typeid(*basePtr) == typeid(Derived)) { // Congratulations! basePtr was indeed a secret agent: Derived }

Just remember, typeid is kind of introverted and does not support hierarchy checks like dynamic_cast.

Performance considerations: Every operation has a price tag!

dynamic_cast and typeid are not free food samples - there's a performance cost attached due to RTTI. If performance is as critical as coffee to a programmer, try out templates or C++20 concepts for type checks.

Compile-time checks using Macros: Because who likes runtime costs?

With C++11, we got the power of macros coupled with metaprogramming, enabling us to mock instanceof checks during compile-time while sipping our coffee during run-time.

#define isType(Type, obj) (typeid(obj) == typeid(Type))

This beauty offers swift, though slightly rigid, performance equivalent to instanceof.

Multiple inheritance: How well do you handle your types?

When you've too many types with dynamic_cast and multiple inheritances around, it's as complex as a season finale plot twist. When caught in this situation, reconsider the design of your classes or consider the direct approach - enum.