References and Runtime Polymorphism
Can I use references with polymorphic classes to achieve runtime polymorphism?
Absolutely! References are a great way to achieve runtime polymorphism in C++. They allow you to work with derived class objects through base class references, enabling you to call virtual functions and get the correct derived class behavior.
Let's look at an example using our Character
class from the lesson:
#include <iostream>
#include <string>
class Character {
public:
Character(const std::string& name)
: mName{name} {}
virtual void Attack() const {
std::cout << mName
<< " performs a basic attack!\n";
}
virtual ~Character() = default;
protected:
std::string mName;
};
class Warrior : public Character {
public:
Warrior(const std::string& name)
: Character{name} {}
void Attack() const override {
std::cout << mName
<< " swings a mighty sword!\n";
}
};
class Mage : public Character {
public:
Mage(const std::string& name)
: Character{name} {}
void Attack() const override {
std::cout << mName
<< " casts a powerful spell!\n";
}
};
void PerformAttack(const Character& character) {
character.Attack();
}
int main() {
Character genericChar{"Generic"};
Warrior warrior{"Conan"};
Mage mage{"Gandalf"};
PerformAttack(genericChar);
PerformAttack(warrior);
PerformAttack(mage);
}
Generic performs a basic attack!
Conan swings a mighty sword!
Gandalf casts a powerful spell!
In this example:
- We define a base
Character
class with a virtualAttack()
method. - We create two derived classes,
Warrior
andMage
, each overriding theAttack()
method. - We define a
PerformAttack()
function that takes aconst Character&
parameter. - In
main()
, we create instances of each class and pass them toPerformAttack()
.
The key here is the PerformAttack()
function. It takes a reference to a Character
, but when we call it with a Warrior
or Mage
, it still calls the correct overridden Attack()
method. This is runtime polymorphism in action!
A few important points:
- The
Attack()
method must be declaredvirtual
in the base class for this to work. - We use
const
references here as we're not modifying the objects. - It's good practice to declare a virtual destructor in the base class when using polymorphism.
References provide a clean syntax for achieving polymorphism, as you don't need to worry about dereferencing pointers. However, remember that unlike pointers, references can't be null and can't be reassigned after initialization.
References
This lesson introduces references, explaining how they work, their benefits, and their role in performance and data manipulation