Full code example (Re: Returning derived class pointer from base
class pointer without casts)
Here is a full code which illustrates what I would like to have (and its
close to my real code as well).
In the code (main.cpp) below I have to do it something like this:
((Animal<int>*)farm.getAnimal(0))->speak(2015);
((Animal<string>*)farm.getAnimal(1))->speak("hello");
But I would like to do it like this:
farm.getAnimal(0)->speak(2015);
farm.getAnimal(1)->speak("hello");
Which is only possible if getAnimal() is able to return the animals real
type (dog here).
So is it possible to return different type with different function
parameter index? The point being that I want to use templates and I also
want to have as simple call as possible, rather without no casts.
the full code:
===============================================
class AnimalBase
{
public:
virtual ~AnimalBase() = 0;
};
AnimalBase::~AnimalBase()
{
std::cout<<"~AnimalBase";
}
template <typename T>
class Animal : public AnimalBase
{
public:
virtual void speak(T speakMore) {}
virtual ~Animal() {std::cout<<"~Animal";}
};
template <typename T>
class Dog : public Animal<T>
{
public:
T m_whatToSpeak; // about age or its name?
void speak(T speakMore);
virtual ~Dog() {std::cout<<"~Dog";}
};
// Specialized functions to speak according to the type of m_whatToSpeak.
// int means that dog is talking about its age and string means that it
talks about
// its name.
template <>
void Dog<int>::speak(int speakMore)
{
std::cout<<"Dogs age is: "<<m_whatToSpeak<<", message:
"<<speakMore<<std::endl;
}
template <>
void Dog<std::string>::speak(string speakMore)
{
std::cout<<"Dogs name is: "<<m_whatToSpeak<<", message:
"<<speakMore<<std::endl;
}
class Farm
{
public:
// AnimalBase* is used in order to dynamically add templated dogs
vector<AnimalBase*> m_animals;
AnimalBase* getAnimal(int i) { return m_animals[i]; }
void addDogs();
~Farm()
{
for(auto a : m_animals)
delete a;
}
};
void Farm::addDogs()
{
// We want the first dog to talk about its age (5)
m_animals.push_back(new Dog<int>());
((Dog<int>*) m_animals[0])->m_whatToSpeak = 5;
// We want the first dog to talk about its name (Willy)
m_animals.push_back(new Dog<std::string>());
((Dog<std::string>*) m_animals[1])->m_whatToSpeak = "Willy";
}
// Depending on what type of dog I have I have to use different types
// for those dogs to be used in class.
int main()
{
Farm farm;
farm.addDogs();
((Animal<int>*)farm.getAnimal(0))->speak(2015);
((Animal<string>*)farm.getAnimal(1))->speak("hello");
return 0;
}