I have a collection of objects that share a common base class, but additionally some of them implement one or more interfaces. When iterating over them, I want to be able to run the methods of these interfaces only if the object is of a class that implements them.
Let's say I have something like this:
include <iostream>
#include <vector>
using namespace std;
class IMovable
{
public:
virtual bool canFly ()
{
return false;
}
virtual bool canSwim ()
{
return false;
}
virtual bool canCrawl ()
{
return false;
}
};
class IFlying: virtual public IMovable
{
public:
virtual void fly () = 0;
};
class IAquatic: virtual public IMovable
{
public:
virtual void swim () = 0;
};
class ITerrestrial: virtual public IMovable
{
public:
virtual void crawl () = 0;
};
class Animal
{
public:
void eat ()
{
cout << "Yummy";
}
};
class Bird:public Animal, public IFlying
{
public:
void fly () override
{
cout << "Fly like a bird";
}
bool canFly () override
{
return true;
}
};
class Frog:public Animal, public IAquatic, public ITerrestrial
{
public:
void swim () override
{
cout << "Swimming frog";
}
void crawl () override
{
cout << "Ribbit";
}
bool canSwim () override
{
return true;
}
bool canCrawl () override
{
return true;
}
};
main ()
{
std::vector < IMovable * >animals;
Frog f;
Bird b;
animals.push_back (&f);
animals.push_back (&b);
for (auto animal:animals)
{
if (animal->canCrawl ())
{
static_cast < ITerrestrial * >(animal)->crawl ();
}
if (animal->canSwim ())
{
static_cast < IAquatic * >(animal)->swim ();
}
if (animal->canFly ())
{
static_cast < IFlying * >(animal)->fly ();
}
return 0;
}
}
This doesn't work because I have virtual inheritance, but if I don't have it the base is ambiguous, and if I don't have the vector set to a base type of the interfaces, I cannot downcast. I cannot use RTTI unfortunately, so that is out of the question.
I wonder if there is perhaps a less convoluted way to achieve this result. Not having to do a bunch of static_casts would be a big bonus.