Polymorphism

Jul 6, 2011 at 1:14pm
I read the tutorial on polymorphism in this site.
But I could imagine nothing that would actually become easier if I used Polymorphism.
So what is the point in their use?
When is it actually beneficial?
Jul 6, 2011 at 2:13pm
Polymorphism let's you treat different but similar types as if they were the same.

Let's say you're writing a game. You have lots of different kinds of enemies that all have different behavior

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Enemy
{
public:
  virtual ~Enemy() { }
  virtual void Update() = 0;  // pure virtual 'Update' function
};

//...

class Goblin : public Enemy  // a Goblin "is an" Enemy
{
public:
  virtual void Update()
  {
    // ... do things that a Goblin would do
  }
};

//...

class Orc : public Enemy  // an Orc "is an" Enemy
{
public:
  virtual void Update()
  {
    // ... do things that an Orc would do
  }
};


You could write different AI code for each different enemy type.

The trick is, because all enemies derive from a common 'Enemy' base class, you can treat them all the same:

1
2
3
4
5
6
7
8
9
10
std::vector<Enemy*>  enemies;  // our array of enemies

// create some enemies -- 2 goblins and an Orc
enemies.push_back( new Goblin );
enemies.push_back( new Goblin );
enemies.push_back( new Orc );

// now when we want to update all enemies, we just call their Update function
for(int i = 0; i < enemies.size(); ++i)
  enemies[i]->Update();


Calling Update like this will automatically do the Goblin's AI if the enemy is a goblin, or the Orc's AI if the enemy is an Orc.


Another nice this is this makes it easy to add new enemy types. All you have to do is derive a new class from Enemy. You don't need to change anything else.
Jul 6, 2011 at 2:31pm
Thanks. That does gives a very good use of polymorphism.
Jul 6, 2011 at 2:43pm
one more...

lets say there existed two classes...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <iostream>
#include <string>
using namespace std;

#define __CALLBACK 

class nameBase
{

private:
	
	nameBase *m_nameBase;
	std::string m_name;		

protected:	

	virtual void __CALLBACK nameChanged()
	{
		std::cout << "nameBase callback" << std::endl;
	}

public:

	void setName(const std::string& name)
	{
		m_name = name;
		m_nameBase->nameChanged();
		
	}

	nameBase(const std::string& name)
	{
		m_nameBase = this;
		m_name = name;
	}		
};

class programmer1 : public nameBase
{
private:

public:		

	programmer1(const std::string& name) : nameBase(name) {}	

	void __CALLBACK nameChanged()
	{
		//programmer1's own code here
		std::cout << "Draw triangle" << std::endl;
	}
};

int main ()
{

	nameBase *obj1 = new programmer1("");
	obj1->setName("obj1");
}


you came and you want to change the implementation of nameChanged() to something else, and you want that it should draw a rectangle now.. so what you did is this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class nisheethNameBase : public nameBase
{

private:
	
public:
	
	nisheethNameBase(const std::string& name) : nameBase(name){}
	
	void __CALLBACK nameChanged()
	{
		//nisheethNameBase's own code here
		std::cout << "draw rectangle" << std::endl;
	}
};

int main ()
{

	nameBase *obj1 = new nisheethNameBase("");
	obj1->setName("obj1");
}


see how automatically your callback will be called without doing anything in the base classes. Although this is just an idea and not a perfect example, but in big code this idea gives a good design to the whole application.

Disch example is a good example and can be used to implement kind of observer pattern. So you learned a pattern also.
Topic archived. No new replies allowed.