I have a program where I have a vector of pointers to a base class where I store instances of multiple different derived classes. All these objects interact with each other in different ways depending on their type and I'd like to implement these interactions in a smart way. I'd prefer to have a mediator class where to keep as much as possible of the code related to these interactions.
Here's a simplified version of what I'd like to achieve:
#include <iostream>
#include <vector>
class Gesture {};
class Rock : public Gesture {};
class Paper : public Gesture {};
class Scissors : public Gesture {};
class Game {
public:
static void play(Rock* first, Rock* second) {
std::cout << "Rock ties with rock." << std::endl;
}
static void play(Rock* first, Paper* second) {
std::cout << "Rock is beaten by paper." << std::endl;
}
static void play(Rock* first, Scissors* second) {
std::cout << "Rock beats scissors." << std::endl;
}
static void play(Paper* first, Rock* second) {
std::cout << "Paper beats rock." << std::endl;
}
static void play(Paper* first, Paper* second) {
std::cout << "Paper ties with paper." << std::endl;
}
static void play(Paper* first, Scissors* second) {
std::cout << "Paper is beaten by scissors." << std::endl;
}
static void play(Scissors* first, Rock* second) {
std::cout << "Scissors are beaten by rock." << std::endl;
}
static void play(Scissors* first, Paper* second) {
std::cout << "Scissors beat paper." << std::endl;
}
static void play(Scissors* first, Scissors* second) {
std::cout << "Scissors tie with scissors." << std::endl;
}
};
int main()
{
Rock rock;
Paper paper;
Scissors scissors;
std::vector<Gesture*> gestures;
gestures.push_back(&rock);
gestures.push_back(&paper);
gestures.push_back(&scissors);
for(int i = 0; i < 3; ++i) {
for(int j = 0; j < 3; ++j) {
// alas, downcasting doesn't happen automagically...
Game::play(gestures[i], gestures[j]);
}
}
return 0;
}
Is there an easy way to achieve downcasting without compile-time knowledge which derived classes are in question? The accepted answer to this question: Polymorphism and get object type in C++ seems to solve my problem, but I'm wondering if I can avoid changes to the derived classes (I'd like to collect the related code into the mediator class, if possible). I suppose I could figure out the derived class with a switch statement that tries to downcast to all the possible derived classes and check which one doesn't return a nullptr
, but this doesn't seem particularly "smart".
Any ideas?