Look at this piece of C++ code:
As you can see, dynamic_cast is used here ("static" is also suitable though), because we know that the return type of new_like() is always the same as its argument (as it uses clone() inside).
#include <string>
#include <iostream>
using namespace std;
class Animal {
public:
string color;
virtual Animal * clone() {
Animal * new_animal = new Animal(*this);
return new_animal;
}
};
class Dog : public Animal {
public:
int fangs;
Dog() : fangs(4) {}
Dog * clone() {
Dog * new_dog = new Dog(*this);
return new_dog;
}
};
class Cat : public Animal {
public:
int tail_length;
Cat() : tail_length(10) {}
Cat * clone() {
Cat * new_cat = new Cat(*this);
return new_cat;
}
};
class Shop {
public:
string animals_color;
Animal * new_like(Animal * a) {
Animal * new_animal = a->clone();
new_animal->color = this->animals_color;
return new_animal;
}
};
int main(void) {
Cat c;
c.color = "white";
Shop s;
s.animals_color = "black";
Cat * new_cat = dynamic_cast<Cat*>(s.new_like(&c));
cout << new_cat->color;
}
As you can see, dynamic_cast is used here ("static" is also suitable though), because we know that the return type of new_like() is always the same as its argument (as it uses clone() inside).
Of course this is ugly. How do you improve this without significant changes?
The simplest solution is to use template method of shop
ReplyDeleteclass Shop {
public:
string animals_color;
template
T * new_like(T * a) {
T * new_animal = a->clone();
new_animal->color = this->animals_color;
return new_animal;
}
};
int main(void) {
Cat c;
c.color = "white";
Shop s;
s.animals_color = "black";
Cat * new_cat = s.new_like(&c);
cout << new_cat->color;
}