There are two ways that you can do this. First, you can use the typeid operator, which returns a type_info structure containing information about the type of the object. For example:
Base* ptr = /* ... */
if (typeid(*ptr) == typeid(DerivedType)) {
/* ... ptr points to a DerivedType ... */
}
Notice that you have to use typeid(*ptr) and not typeid(ptr) here. If you use typeid(ptr), then you’ll get back a type_info object for Base*, since the pointer has type Base* regardless of what it points at.
An important point to note is that this will check if what ptr points at is exactly a DerivedType. If ptr is pointing at an object of a type derived from DerivedType (maybe an EvenMoreDerivedType), this code will not work correctly.
An alternative way of checking whether you are pointing at an object of some type that is a bit more robust is to use the dynamic_cast operator. dynamic_cast performs a checked typecast at runtime that will yield a valid pointer if the cast succeeds and nullptr otherwise. For example:
Base* ptr = /* ... */;
auto* derived = dynamic_cast<DerivedType*>(ptr);
if (derived) {
/* ... points to a DerivedType ... */
}
This has the added advantage that if ptr points at something like an EvenMoreDerivedType, the cast will still succeed because EvenMoreDerivedType inherits from DerivedType.
As a final thought, you sometimes see code like this:
Base* ptr = /* ... */
if (auto* derived = dynamic_cast<DerivedType*>(ptr)) {
/* ... points to a DerivedType ... */
}
This locally-scopes the derived pointer to the body of the if statement and uses the fact that nonzero values evaluate to true in C++. I personally find this easier to read and less error-prone, but by all means go with what’s easiest for you.
Hope this helps!