I've got this code I need to link together by creating the implementation (.cpp) file for.
I've been given main.cpp and a header file. I need help on my Zoo.cpp file, specifically now on the "addAnimaltoZoo" function.
Here's what I've got so far...


main.cpp:

#include <iostream>
using namespace std;
#include "Zoo.h"

int main()
{
    Zoo z;
    Horse * prince = new Horse(1550, "Prince");
    Cow * mollie = new Cow(1220, "Mollie");
    Snake * sly = new Snake(5, "Sly");
    Cow * milkey = new Cow(1110, "Milkey");

    z.addAnimaltoZoo(prince);
    z.addAnimaltoZoo(mollie);
    z.addAnimaltoZoo(sly);
    z.addAnimaltoZoo(milkey);
    
    cout << "The total weight for the zoo is "
         << z.getTotalZooWeight() << " pounds." << endl;

    z.makeAllNoisesInZoo();

    return 0;    
}

Zoo.h:

// ***************** zoo.h *************************

enum animal_type {t_Horse, t_Cow, t_Snake};

class Animal
{
   double weight;
   animal_type type;
   string name;

public:
   Animal(double w, animal_type t, char * n): 
                     weight(w), type(t), name(n)
   {
   }
   void makeNoise()
   {
      cout << "This should never be called for any animal"
                  << endl;
   }

   const char *getName()
   {
      return name.c_str();
   }


   double getWeight()
   {
      return weight;
   }

   animal_type getAnimalType()
   {
      return type;
   }

};

class Horse : public Animal
{
public:
    Horse (double weight, char * name);
    void makeNoise(); // Horses should say Whinney
};

class Snake : public Animal
{
public:
    Snake (double weight, char * name);
    void makeNoise(); // Snakes should say Hiss
};


class Cow : public Animal
{
public:
    Cow (double weight, char * name);
    void makeNoise();  // Cows should say Mooo
};

const int ZOO_SIZE=10;

class Zoo
{
    
    Animal * animals[ZOO_SIZE];
    int animalCount;
public:
    Zoo(): animalCount(0)
    {
    }

    // The following method adds the specified animal to the Zoo
    void addAnimaltoZoo(Animal *a);

    // The following calls the makeNoise routines for all of the 
    // animals in the zoo
    void makeAllNoisesInZoo();

    // The following returns the total weight of the Zoo
    double getTotalZooWeight();
};

And my attempt so far at the Zoo.cpp:

#include <iostream>
using namespace std;
#include "Zoo.h"



Horse::Horse (double weight, char * name) :
	Animal (weight, t_Horse, name)
{}


 //Horses should say Whinney
void Horse::makeNoise()
{
	cout << "Whinney";
}

Snake::Snake (double weight, char * name) :
	Animal (weight, t_Snake, name)
{}


 // Snakes should say Hiss
void Snake::makeNoise()
{
	cout << "Hiss";
}


Cow::Cow (double weight, char * name) :
	Animal (weight, t_Cow, name)
{}


  // Cows should say Mooo
void Cow::makeNoise()
{
	cout << "Mooo";
}



    // The following method adds the specified animal to the Zoo
void Zoo::addAnimaltoZoo(Animal *a)
{
	if (animalCount < ZOO_SIZE)
	{
		Animal *b = new Animal(a);
		animals[animalCount++] = b;
	}
}

    // The following calls the makeNoise routines for all of the 
    // animals in the zoo
void Zoo::makeAllNoisesInZoo()
{
}

    // The following returns the total weight of the Zoo
double Zoo::getTotalZooWeight()
{
	return 0;
}

Any help please!

I have to go back and redo it all with Polymorphism after I figure this part out.

Recommended Answers

All 10 Replies

I haven't looked over all your code, but the addAnimalToZoo() function looks fine to me.

Polymorphism just means that you can derive from more than one class at a time. So, for example, you could make a SnakeHorse.

I think the way I have my function set up would work normally, but since the zoo array is set to a const max, it won't allow me to "convert from 'Animal *' to ' const Animal &'." Let me know what you think, when you get a chance please!...

Thanks

Sure it will. Pay attention to what is being made const: ZOO_SIZE is const. After the array is created, it has no other effect (since you can't change the size of an array after creating it anyway). Animal *animals[ ZOO_SIZE ] is not const. You can change elements of the array (for example: animals[ 2 ] = new Horse( 750.0, "George" ); ).

Each animal you create is not const.

When you write a function like: void do_something( const Animal &a ) what you are saying is that a is const. That is, your function gets an animal by reference, but is not allowed to change the animal in any way. When you use the function it does not matter whether the animal you give it is mutable or not.

Likewise, when you have a method like: void MyClass::MyMethod() const what that means is that the method is not allowed to change *this in any way.

Hope this helps.

Ok, I uderstand what you're saying, and that's what I thought too. However, when I attempt to compile what I have, Vis Studio tells me that:


'Animal::Animal(const Animal &)' : cannot convert parameter 1 from 'Animal *' to 'const Animal &'


Maybe I'm doing something else wrong in there...??

Ok, so in regards to my last post, I think I figured it out. I simply needed to pass in the pointer of a, rather than just a. Like so:

void Zoo::addAnimaltoZoo(Animal *a)
{
	if (animalCount < ZOO_SIZE)
	{
		Animal *b = new Animal(*a);
		animals[animalCount++] = b;
	}
}

Now this is what my entire cpp file looks like now, and I just need help with the makeAllNoisesInZoo function now please. I have it setup right now to call to the Animal class, and that won't work. I need to find a way to call THROUGH the Animal class into the correct class of the animal at hand. Any help/pointers please?

Here's what I got:

Zoo.cpp:

#include <iostream>
using namespace std;
#include "Zoo.h"



Horse::Horse (double weight, char * name) :
	Animal (weight, t_Horse, name)
{}



void Horse::makeNoise()
{
	cout << "Whinney";
}

Snake::Snake (double weight, char * name) :
	Animal (weight, t_Snake, name)
{}



void Snake::makeNoise()
{
	cout << "Hiss";
}


Cow::Cow (double weight, char * name) :
	Animal (weight, t_Cow, name)
{}



void Cow::makeNoise()
{
	cout << "Mooo";
}



void Zoo::addAnimaltoZoo(Animal *a)
{
	if (animalCount < ZOO_SIZE)
	{
		Animal *b = new Animal(*a);
		animals[animalCount++] = b;
	}
}


void Zoo::makeAllNoisesInZoo()
{
	for (int i=0; i < animalCount; i++)
	{
		Animal *a = animals[i];
		cout << a->getName() << " says " ;
		a->makeNoise();
	}
}


double Zoo::getTotalZooWeight()
{
	double total=0.0;

	for (int i=0; i < animalCount; i++)
	{
            Animal *a = animals[i];
            total += a->getWeight();
	}
	return total;
}

You need to read up on virtual methods.

Currently, Animal.makeNoise() is statically bound. In "zoo.h" you must say: virtual void makeNoise() so that the derived classes can override the method with their own versions.

Next, in your addAnimalToZoo() method, you have a memory leak. Let's trace your code:
1. in main() you allocate a new Horse.
2. in addAnimalToZoo() you allocate a new Animal (and use the default copy constructor).
3. in addAnimalToZoo() you put the newly allocated Animal in your array of animals
4. you forget about the Horse
5. in makeAllNoisesInZoo() you ask the first animal (whose type is Animal, not Horse, due to step 2) to make a noise. Animals are abstract creatures so aren't supposed to actually exist: Horses exist, Snakes exist, Cows exist.

My recommendations are
1. make Animal.makeNoise() a purely virtual function: virtual void makeNoise() = 0; Now an Animal class can't actually be instantiated. The user must instead instantiate a derived class (Horse, Snake, or Cow).

2. use the new-ed Animal object passed into addAnimalToZoo() instead of creating another Animal (which you can't do now anyway after recommendation #1):

void Zoo::addAnimaltoZoo(Animal *a)
{
	if (animalCount < ZOO_SIZE)
	{
		animals[animalCount++] = a;
	}
}

Fix that, give it a compile and run, and see if you can't fix the output error.

Hope this helps.

Isn't that how I'm going to do it when I go back and do it polymorphically though? I'm pretty sure the virtual function is for polymorphism....

I took your advice for the addAnimalToZoo function though. That seems to work just fine.

The reason we're doing it this way, is that he wants us to truly appreciate polymorphism, so he's making us do it first without using virtual. How can i set it up long ways to still make all the noise?

Ah.

Virtual functions are the core of Object Oriented Programming --you can't do it without them. (Otherwise you are just doing "object-based" programming --or playing with structs that have functions attached.)

I think your professor wants you to understand what it is that OOP offers (i.e. what the benefit is from using virtual functions).

Part of the Animal type is an enum indicating what animal it is. If you can't use virtual functions you will have to change your makeAllNoisesInZoo() to use a giant if..else or a giant switch statement to check what kind of animal you have, then call the appropriate animal's makeNoise() function. if (a->getAnimalType() == t_Horse) ((Horse *)a)->makeNoise(); I was thinking of multiple-inheritance when you said "polymorphism". Sorry.

Hope this helps.

Yea it's deff a drag to do it this way, but that's why he's hoping we'll REALLY appreciate the beauty of polymorphism after we go through all this mess!! I believe this is how I want my switch statement set up then...right?...:

void Zoo::makeAllNoisesInZoo()
{
	for (int i=0; i < animalCount; i++)
	{
		Animal *a = animals[i];
		cout << a->getName() << " says ";
		switch(a->getAnimalType())
		{
		case t_Horse:
			{
				((Horse *)a)->makeNoise();
				break;
			}
		case t_Cow:
			{
				((Cow *)a)->makeNoise();
				break;
			}
		case t_Snake:
			{
				((Snake *)a)->makeNoise();
				break;
			}
		default:
			{
				a->makeNoise();
				break;
			}
		}
		cout << endl;
	}
}

Now, for polymorphism is the makeNoise function the only function I need to adjust in order to make it work? Or do I need to change everything?

Nvrmnd I figured the rest out. Thanks for all your help! :)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.