Polymorphic Programming!

Started by
7 comments, last by Rebooted 17 years, 6 months ago
Hello, Im trying to understand polymorphism and I created a little program to try and illustraight its usage, but I've read that polymorphism is used for less typing, but in my example program, it seems like there is extra typing. Please help me, it feels like Im doing something wrong here. NOTE: There are no errors, just design problems. Thanks for any help! Main:

/************************************************************
*
* Name: Brandon Wall
* App Name: Polymorphism Test
* App Date: 10/7/06
* App Desc: Illustrates how to understand and use polymorphism
*           along with inheritance.
*
************************************************************/

#include "Animal.h"
#include "Cat.h"
#include "Dog.h"

int main( int argc, char* argv[] )
{
	
	Animal * animal = new Cat();

	animal->Eat();
	animal->Walk();
	animal->Talk();
	animal->Sleep();
	animal->WakeUp();

	// voids memory leaks
	delete animal;

	// creates a dog
	animal = new Dog();

	animal->Eat();
	animal->Walk();
	animal->Talk();
	animal->Sleep();
	animal->WakeUp();

	delete animal;

	return 0;
}

Cat.h

/**********************************************************
*
* File Name: Cat.h
* File Desc: Derived from Animal
*
**********************************************************/

#ifndef CAT_H
#define CAT_H

#include <iostream>
#include "Animal.h"

struct Cat : public Animal
{

	void Eat();
	void Walk();
	void Talk();
	void Sleep();
	void WakeUp();

};

#endif

Cat.cpp

/***********************************************************
*
* File Name: Cat.cpp
* File Desc: Cat Member Function Definitions
*
***********************************************************/

#include "Cat.h"

void Cat::Eat() {
	std::cout << "The Kitty is eating\n";
}

void Cat::Walk() {
	std::cout << "The Kitty is Walking\n";
}

void Cat::Talk() {
	std::cout << "The Kitty is talking\n";
}

void Cat::Sleep() {
	std::cout << "The Kitty is sleeping\n";
}

void Cat::WakeUp() {
	std::cout << "The Kitty has woken up\n";
}

Dog.h

/***********************************************************
*
* File Name: Dog.h
* File Desc: Derived from Animal
*
***********************************************************/

#ifndef DOG_H
#define DOG_H

#include <iostream>
#include "Animal.h"

struct Dog : public Animal
{

	void Eat();
	void Walk();
	void Talk();
	void Sleep();
	void WakeUp();

};

#endif

Dog.cpp

/***********************************************************
*
* File Name: Dog.cpp
* File Desc: Dog Member function Definitions
*
***********************************************************/

#include "Dog.h"

void Dog::Eat() {
	std::cout << "The Doggy is eating\n";
}

void Dog::Walk() {
	std::cout << "The Doggy is Walking\n";
}

void Dog::Talk() {
	std::cout << "The Doggy is talking\n";
}

void Dog::Sleep() {
	std::cout << "The Doggy is sleeping\n";
}

void Dog::WakeUp() {
	std::cout << "The Doggy has woken up\n";
}

Advertisement
Quote:Original post by NUCLEAR RABBIT
Hello,

Im trying to understand polymorphism and I created a little program to try and illustraight its usage, but I've read that polymorphism is used for less typing, but in my example program, it seems like there is extra typing. Please help me, it feels like Im doing something wrong here.

NOTE: There are no errors, just design problems.
Your example looks fine; it illustrates the basic idea behind polymorphism nicely.

If anything, 'less typing' is just one of many possible side effects of using polymophism. It certainly isn't it's raison d'etre, per se, so I wouldn't get too hung up on it.

I think as you explore polymorphism and inheritance further its uses and benefits will start to become more apparent. To get you started, I'll give one example based on what you posted. Since Dog and Cat inherit from a common base class with virtual functions, they can each be represented by and accessed via an Animal*, as your example shows. You could then, for example, maintain a container (list, vector, or what have you) of Animal*'s, and then decide at run time whether these Animals will be Cats, Dogs, or both. Furthermore, you can re-assign the pointers to new objects of different types on the fly.

Throughout, the interface remains the same. The code that iterates through the container and calls Eat(), Sleep(), and so on, doesn't know about or care about the actual type of the object on which it's being called. This may be what was meant by the 'less typing' comment; in many cases polymophism can take the place of multiple blocks of code, if/else sequences, or switch statements.

That's a very simplistic overview, but maybe it'll help clear things up a bit.
For the less typing comment...

Imagine you had a zoo, with 1000 animals. Then you would certainly be saving typing, right? Just use an animal pointer vector and loop through each pointer, dereference, and call the method (make sure its virtual in animal!).

Now extend that to games. Instead of animals, maybe you have renderable objects in your video engine. A renderable object could be a 3d mesh, part of your GUI, a sprite, a billboard, a particle, et cetera. Each one rendering uniquely. However, because they all come from the same base class, something like Renderable, all your 'render logic' needs to do is loop through the list of objects needing to be rendered and call their rendering method. Then each class can take care of itself.
If you're intent on saving typing, factor out the repetive animal.eat() animal.walk() etc. code into a seperate function taking an Animal*. Or as a member function to Animal that isn't virtual.
Whee, fun with polymorphic handles.

#include "animal.h"class AnimalHandle{public:   AnimalHandle(Animal * animal) : _animal(animal) {}   AnimalHandle(const AnimalHandle & from) : _animal(from._animal->clone()) {}   AnimalHandle & operator=(const AnimalHandle & rhs)   {      if (this != &rhs)      {         delete _animal;         _animal = rhs._animal->clone();      }      return *this;   }   ~AnimalHandle()   {      delete _animal;   }   void Eat()   {      _animal->Eat();   }   void Walk()   {      _animal->Walk();   }   void Talk()   {      _animal->Talk();   }   void Sleep()   {      _animal->Sleep();   }   void WakeUp()   {      _animal->WakeUp();   }private:   Animal * _animal;};AnimalHandle myDog(new Dog());AnimalHandle myCat(new Cat());myDog.Walk();myDog.Talk();myCat.Sleep();myCat.WakeUp();AnimalHandle yourDog(myDog);yourDog.Sleep();// Hooray, no pointers!


About clone()

EDIT: Whoops, forgot to include the Animal pointer in the class.
This is the real reason.
Zahlman's link above is great.

Just to talk the idea to death. Polymorphism is almost exactly a replacement for cases where in C people would use an ever-growing switch statement to call the right function for the object in question .... aka if object.vehicle_type == car DoX() else if object.vehicle_type == truck DoY()

All polymorphism really is, is a formal system that automatically does that in an extremely efficient way (using function pointers in vtable). In addition to doing the above, the way C++ inheiritance works, you automatically get the behavior of you base class if you don't need special code - so you don't have to write ANY code to make a class have the same behavior as its base class, you only have to write the differences.

Basically polymorphism is like a really predictable, safe, managable alternative to type-based switch statements.

About the only thing wrong with OO class based virtual polymorphism is that your object tree cannot easily be sliced up multiple ways for multiple different interfaces (aspect oriented programming), it can be done, but is not easy to properly manage all the details.
Hey All,

Thanks for all the helpful links, and explinations. If its not asking to much, I have ne more question, is polyorphic programming only using virtual functions, or are there other ways? All the ways I've seen user virtal functions.

Once again, Thanks for all the help!
Quote:Original post by NUCLEAR RABBIT
Hey All,

Thanks for all the helpful links, and explinations. If its not asking to much, I have ne more question, is polyorphic programming only using virtual functions, or are there other ways? All the ways I've seen user virtal functions.

Once again, Thanks for all the help!
So-called ad hoc polymorphism is available via virtual functions, overloading and templates. Another form formally known as parametric polymorphism is also available in C++ via templates. Parametric polymorphism means one implementation for all types; ad hoc on the other hand means multiple implementations for multiple types.

Templates can only bind statically, while virtual functions bind dynamically.

This topic is closed to new replies.

Advertisement