Storing polymorphic types in a std::vector
is a common requirement when working with class hierarchies. However, it requires some special considerations due to object slicing and memory management. Let's explore how to do this correctly using pointers or smart pointers.
The simplest way to store polymorphic types is using raw pointers:
#include <iostream>
#include <vector>
class Character {
public:
virtual void speak() const = 0;
virtual ~Character() = default;
};
class Warrior : public Character {
public:
void speak() const override{
std::cout << "I am a warrior!\n";
}
};
class Mage : public Character {
public:
void speak() const override{
std::cout << "I am a mage!\n";
}
};
int main(){
std::vector<Character*> characters;
characters.push_back(new Warrior());
characters.push_back(new Mage());
for (const auto& character : characters) {
character->speak();
}
// Don't forget to delete!
for (auto character : characters) {
delete character;
}
}
I am a warrior!
I am a mage!
However, this approach requires manual memory management, which can lead to memory leaks if not handled correctly.
A better approach is to use smart pointers, particularly std::unique_ptr
or std::shared_ptr
:
#include <iostream>
#include <vector>
#include <memory>
class Character {
public:
virtual void speak() const = 0;
virtual ~Character() = default;
};
class Warrior : public Character {
public:
void speak() const override{
std::cout << "I am a warrior!\n";
}
};
class Mage : public Character {
public:
void speak() const override{
std::cout << "I am a mage!\n";
}
};
int main(){
std::vector<std::unique_ptr<Character>>
characters;
characters.push_back(
std::make_unique<Warrior>());
characters.
push_back(std::make_unique<Mage>());
for (const auto& character : characters) {
character->speak();
}
// No need to manually delete
}
I am a warrior!
I am a mage!
This approach is safer as it automatically manages memory, preventing leaks.
Remember, when using polymorphic types, always declare the base class destructor as virtual to ensure proper cleanup of derived classes.
By using these techniques, you can effectively store and manage polymorphic types in a std::vector
, allowing for flexible and type-safe operations on collections of objects with different derived types.
Answers to questions are automatically generated and may not have been reviewed.
std::vector
Explore the fundamentals of dynamic arrays with an introduction to std::vector