Using RTTI with smart pointers can provide a powerful combination for managing polymorphic objects safely. Here's how you can effectively use them together:
dynamic_pointer_cast()
Instead of using dynamic_cast()
with raw pointers, use std::dynamic_pointer_cast()
with smart pointers. This function performs a safe downcast and returns a null pointer if the cast fails.
#include <iostream>
#include <memory>
class Monster {
public:
virtual ~Monster() {}
};
class Dragon : public Monster {
public:
void breatheFire() {
std::cout << "Dragon breathes fire!\n";
}
};
void handleMonster(
std::shared_ptr<Monster> monster
) {
auto dragon =
std::dynamic_pointer_cast<Dragon>(monster);
if (dragon) {
dragon->breatheFire();
} else {
std::cout << "This is not a dragon.\n";
}
}
int main() {
auto dragon = std::make_shared<Dragon>();
auto monster = std::make_shared<Monster>();
handleMonster(dragon);
handleMonster(monster);
}
Dragon breathes fire!
This is not a dragon.
typeid()
with Smart PointersYou can use typeid()
with smart pointers by dereferencing them. This is safe because smart pointers ensure the object exists.
#include <iostream>
#include <memory>
#include <typeinfo>
class Monster {/*...*/};
class Dragon : public Monster {/*...*/};
void identifyMonster(
const std::shared_ptr<Monster>& monster
) {
if (typeid(*monster) == typeid(Dragon)) {
std::cout
<< "This is a Dragon!\n";
} else {
std::cout
<< "This is a different kind of Monster.\n";
}
}
int main() {
auto dragon = std::make_shared<Dragon>();
auto monster = std::make_shared<Monster>();
identifyMonster(dragon);
identifyMonster(monster);
}
This is a Dragon!
This is a different kind of Monster.
If you prefer a custom type identification system, you can still use it effectively with smart pointers.
#include <iostream>
#include <memory>
enum class MonsterType { Base, Dragon };
class Monster {
public:
virtual ~Monster() {}
virtual MonsterType getType() const {
return MonsterType::Base;
}
};
class Dragon : public Monster {
public:
MonsterType getType() const override {
return MonsterType::Dragon;
}
void breatheFire() {
std::cout << "Dragon breathes fire!\n";
}
};
void handleMonster(
const std::shared_ptr<Monster>& monster
) {
if (monster->getType() == MonsterType::Dragon) {
auto dragon =
std::static_pointer_cast<Dragon>(monster);
dragon->breatheFire();
} else {
std::cout << "This is not a dragon.\n";
}
}
int main() {
auto dragon = std::make_shared<Dragon>();
auto monster = std::make_shared<Monster>();
handleMonster(dragon);
handleMonster(monster);
}
Dragon breathes fire!
This is not a dragon.
By combining RTTI with smart pointers, you get the benefits of runtime type checking and automatic memory management, leading to safer and more robust code when dealing with polymorphic objects.
Answers to questions are automatically generated and may not have been reviewed.
typeid()
Learn to identify and react to object types at runtime using RTTI, dynamic casting and the typeid()
operator