When to use polymorphism

Started by
16 comments, last by Jason Z 10 years, 3 months ago

In which cases I should use polymorphism ?

I know that if we create classes mammal, cat and a dog like:


class mammal
{
	...
	virtual void Run();
};


class cat : public mammal
{ 
	...
	Run();
};


class dog : public mammal	
{
	...
	Run();
};


void main()
{
	mammal *pMammal1;
	mammal *pMammal2;
	cat *pCat = new cat();
	dog *pDog = new dog();

	pMammal1 = pCat;
	pMammal2 = pDog;
}

we can access cat and dog trough mammal. But what is the use of this, when we can implement this ? Why not just put Run() inside cat and dog without having mammal ?

Advertisement

How can you access this function??? I thought you need inheritance but there is nothing just three seperated classes...

you would need something like:


class mammel
{
public:
     virtual void run();
};

class dog : public mammel
{
public:
    virtual void run();
};

class cat : public mammel
{
public:
virtual void run(); 
};

but perhaps i am wrong and just learned it wrong.

With polymorphie you recive a behavior "similar" to an array/list of functionpointer which do there job everytime they are called but here instead of an array/list you have

the class herachie with overrided functions but in case you need an different behavior of an function which was overriden but you need the original with help of polymorphie you could access this function dynamically. // just a very hard simplification

You use a polymorphic function when you want to refer to a group of objects by their common base class, even if each object can have different behavior. This is useful when the objects are created at runtime and are not known when you are writing your code. Regardless of which type of mammal it is, you can access its methods with a common, well defined interface. This is typically called dynamic polymorphism since the types can be dynamically (at runtime) determined.

An alternative method would be to use template functions which would produce a different version of a function for each of the mammal sub-classes when the template was instantiated. Using a generic method like this provides static polymorphism, since the types are determined at compile time (i.e. when each template is instantiated, the types are fully known).

The two cases provide different benefits (generic access to objects), and both have some detriments (runtime cost for dynamic, compilation time and code size for static).


Why not just put Run() inside cat and dog without having mammal ?

Because then you wouldn't be able to write code that just deals with mammal (i.e. doesn't care if something is a dog or a cat - thus the same code can apply to any Mammal).

Lets say you want all your mammals to run, with polymorphism you can put all your mammals in a single mammal array and call their run function. Without polymorphism you'll have to keep a list of dogs, cats etc. and call their run function.

How can you access this function??? I thought you need inheritance but there is nothing just three seperated classes...

Yea, I forgot to put public mammal. I fixed it now.

So polymorphism is similar to the use of interfaces. If I am not wrong interfaces are classes that contain methods that will be used in multiple other classes, like Run() method here ?

Lets say you want all your mammals to run, with polymorphism you can put all your mammals in a single mammal array and call their run function. Without polymorphism you'll have to keep a list of dogs, cats etc. and call their run function.

IMHO being able to lazily throw all objects into a huge list to avoid having specialized lists is not sufficient reason for using virtual methods, because the specialized lists could directly store the objects, but the single list would be more complicated in some other way as it needs to store pointers and would necessitate many useless pointer indirections to separately allocated objects and virtual calls.

I think there needs to be some other reason to use virtual methods, for example, being able to hide some low level implementation details or interfacing with library code.

I dont really like the example with the mammal, dog and cat, because in a game the code for letting them run would probably be the same for all kinds of living things with legs and a single class could be used for them.

To start with, C++ offers several distinct forms of polymorphism, each one with different use cases in mind (and different trade-offs).

To be able to make an informed choice, it's a good idea to become familiar with them all:

http://accu.org/index.php/journals/538

You'll learn some of the trade-offs the hard way, after discovering that working on your game (or other program) becomes harder over time, when adding more features forces you to go back to the old code that wasn't written with them in mind, etc. And that's OK, this is how you learn and improve -- as long as you Refactor Mercilessly!

It's especially worth noting that run-time polymorphism is very much possible (and arguably cleaner!) without inheritance -- I strongly recommend watching this:

http://channel9.msdn.com/Events/GoingNative/2013/Inheritance-Is-The-Base-Class-of-Evil

How can you access this function??? I thought you need inheritance but there is nothing just three seperated classes...

Yea, I forgot to put public mammal. I fixed it now.

So polymorphism is similar to the use of interfaces. If I am not wrong interfaces are classes that contain methods that will be used in multiple other classes, like Run() method here ?

With an interface, every class has to define the method separately even if each has identical code. With a class, you have default behavior (unless you used a pure virtual function) that is only overridden when necessary. So you could have mammal::run() be the same code for every mammal like wintertime mentions, but you could have mammal::makeNoise() result in "meow" for a cat and "woof" for a dog. And if you had a weird mammal that runs differently, you could override run() just for that one mammal without needing to write run() code for every single type of mammal you have defined.

I agree with wintertime that you should not use polymorphism just to use it though, and it should be used when it is actually solving a problem that is otherwise difficult to solve.


It's especially worth noting that run-time polymorphism is very much possible (and arguably cleaner!) without inheritance -- I strongly recommend watching this:

http://channel9.msdn.com/Events/GoingNative/2013/Inheritance-Is-The-Base-Class-of-Evil

Actually Sean Parent's solution that you mention there does indeed use inheritance - it is just encased into an inner base class that is insulated from the user. That's strictly a technicality though...

I tried this out to implement a form of a mixed object graph, and it works like a charm! Type erasure for the win!

This topic is closed to new replies.

Advertisement