SigGP
SigGP

Reputation: 776

Creating a new instance of the class based on the existing instance

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

Answers (2)

Quentin
Quentin

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

didiz
didiz

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

Related Questions