Reputation: 776
I have many classes which represent different kinds of animals. The idea is that if two animals of the same species meet then new animal of this species should be created - it means that I want to create a new intance of the specific class in this situation. If bears will meet i want to create new instance of bear, when bats meet then new instance of bat.
How can I achieve this goal without duplicating code? I want to avoid making individual if condition for each class (animal). I'm looking for the solution where new instance of a class will be created automatically based on the class of the existing instance.
Upvotes: 1
Views: 220
Reputation: 63114
Since you know that both parent object must have the same type, you don't quite need the usual double-dispatching solutions -- these are made to deal with all possible combinations.
Let's just use a slightly modified variant of the Clone pattern. Animal
, the base class, gets a pure virtual cloning function:
struct Animal {
virtual std::unique_ptr<Animal> mateWith(Animal const &other) const = 0;
};
Then, every subclass implements this method, checking through RTTI that the other Animal
is actually the right type:
struct Bear : Animal {
std::unique_ptr<Animal> mateWith(Animal const &other) const override {
auto &otherBear = dynamic_cast<Bear const &>(other);
return std::make_unique<Bear>(*this, otherBear);
}
};
This will throw std::bad_cast
if the other animal is not a bear. You can also replace this with some other error handling:
struct Bear : Animal {
std::unique_ptr<Animal> mateWith(Animal const &other) const override {
auto *otherBear = dynamic_cast<Bear const *>(&other);
if(!otherBear) {
// This is not a bear!
}
return std::make_unique<Bear>(*this, *otherBear);
}
};
Upvotes: 2
Reputation: 1099
You can compare the types generically using the following:
#include <typeinfo>
if ( typeid(YourClass1) == typeid(YourClass2) )
// do something
To create a new instance, add a pure virtual clone to your Base class, then implement it in every animal.
You can also add a name field to the Base class, and compare with that.
class Animal{
public:
virtual shared_ptr<Animal> clone() = 0;
virtual const string & getname() = 0;
};
class Bear: public Animal{
public:
virtual shared_ptr<Animal> clone()
{
return shared_ptr<Animal>(new Bear());
}
virtual const string & getname()
{
return "bear";
}
};
int main(int argc, const char * argv[])
{
Bear b1;
Bear b2;
shared_ptr<Animal> b3;
if ( b2.getname() == b2.getname() )
b3 = ( b1.clone() );
...
}
Upvotes: 1