Suppose I have a class, Animal, that contains the virtual method eat(). Now suppose Dog is derived from Animal, and also implements eat().
Now somewhere else, I have a class Barn with a feed method that takes Animal& as a parameter. How can I force class Barn to call Dog's eat, when a Dog is passed to feed?

When creating the eat() function in Animal , set it equal to 0. for example:

class Animal
{
    void eat()=0;
};

Edited 3 Years Ago by pyTony: fixed formatting

Is this the only way!? If I do this, I cannot instantiate Animal, which, in the case of the actually classes I'm going to use, isn't necessary. But what I would like to do is hold a std::vector of Animals. NOT animal pointers, but actual animals in the Farm class.
For all the things I like about C++, I think the way they do interfaces is stupid. In Java, it's so much more intuitive.
Heh, these are symbolic class names, by the way. It's not like I've got a binary agriculture going on.

Now that I think about it, what you have should already work. When you call the eat method, is it calling the wrong one?

Well, I mean, suppose we have the situation I just described, but Farm is like this:

class Farm : public Animal
{
     public:
     Farm()
     void add(Animal& animal)
     {
          animals.push_back(animal);
     }
     void feed()
     {
          for(int i...blah blah blah)
          {
               animals[i].eat();
          }
     }
     private:
     std::vector<Animal> animals;
}

Now what I want is to be able to pass in a Dog, a Zebra, or a Liger to my add method, and have the feed method call each derived classes eat method. I havn't found a way to make Animal contain pure virtual functions and allow a std::vector to hold it (since it's abstract). I could hold a pointer to animals in std::vector, but I don't want to do that, since the data could dissappear outside the class, and we would be in a world of hurt. Does this make sense?

Yes, when I call the eat method, it's calling the base class' eat, since I am passing in an Animal reference, not a derived class reference (such as Dog).

Here's the deal - you need the 'virtual' word in the Animal class when defining eat(). (Don't do the =0)

See this example:

#include <iostream>
using namespace std;
class Animal
{
		public:
		virtual void eat()
		{
				cout<<"I'm an animal"<<endl;
		}
};
class Dog : public Animal
{
		public:
		void eat()
		{
				cout<<"I eat like a dog"<<endl;
		}
};
class Cat : public Animal
{
		public:
		void eat()
		{
				cout<<"I eat like a cat"<<endl;
		}
};
void test ( Animal & a);
int main()
{
		Animal a;
		Dog b;
		Cat c;
		test ( a );
		test ( b );
		test ( c );
		return 0;
}
void test ( Animal & a)
{
		a.eat();
}
./Temp
I'm an animal
I eat like a dog
I eat like a cat

Maybe I should spell that out:

Dog dog();
Farm farm();
farm.add(dog);
farm.feed(); // this is calling Animal.eat(), NOOOOO!!!

What you just said makes sense, and it is what I would intuitively think. Maybe it's something else...a good scan over my code...

By the way, what is the difference between

Dog : virtual public Animal

and

Dog : public Animal

?

Not sure about your question, I can tell you that I only got what you wanted to work (with the vectors, when I made the vector store pointers of Animal). I think it has something to do with the fact that push_back makes a copy of the parameter, so I think it copies it as an Animal (there's probably something you can do by creating your own copy constructors, but I'm not sure...). here's my example if it helps.

#include <iostream>
#include <vector>
using namespace std;
class Animal
{
		public:
		virtual void eat()
		{
				cout<<"I'm an animal"<<endl;
		}
};
class Dog : public Animal
{
		public:
		void eat()
		{
				cout<<"I eat like a dog"<<endl;
		}
};
class Cat : public Animal
{
		public:
		void eat()
		{
				cout<<"I eat like a cat"<<endl;
		}
};
class Farm
{
		public:
		vector<Animal *> myVec;
		void add( Animal *a )
		{
				myVec.push_back( a );
		}
		void printout()
		{
				for ( unsigned int i=0;i< myVec.size();i++)
				{
						myVec[i]->eat();
				}
		}
};
int main()
{
		Farm myFarm;
		Animal a;
		Dog b;
		Cat c;
		myFarm.add( &a );
		myFarm.add( &b );
		myFarm.add( &c );
		myFarm.printout();
		return 0;
}
/arpa/af/d/dhoffman>./Temp
I'm an animal
I eat like a dog
I eat like a cat

Thanks for all the help. I can't have pointers in the vector though...'cause if I pass a pointer in the Farm add method, and the data disappears outside of the class, won't that be a bad reference?

Sounds reasonable, though when you were doing 'Animal &' I think you were running the same risk... Hopefully someone will be able to help - I definitely think it has to do with copy constructors... I'll play around a little more and see if I can figure it out.

Well, I figured out that you the base class eat is always called when from vector<Animal>.eat(), but not from vector<Animal*>.eat(). I guess the reasons for this are obvious.

I think what I could do is make a clone method in each class that creates a new instance, clones it's data, and returns a pointer to that new instance. This way, I can just store animals=animal->clone() and I think I would be safe, just as long as I clean up in Farms destructor!

If look at my example, I don't think any cleanup was required because I didn't do a 'new', and I didn't need a clone method...

By the way, what is the difference between

Dog : virtual public Animal

and

Dog : public Animal

?

The difference is that you choose to inhertit an entire class virtual or not. This may come in handy when you face a dreaded diamond construction.

This article has been dead for over six months. Start a new discussion instead.