According to my book, if I want to make an array of objects that are not in the same class but in the same class hierarchy, I need to use pointers:
class text
{
public:
void write(string text);
void show();
private:
string texte;
};
void text::write(string text)
{
texte = text;
}
void text::show()
{
cout << texte;
}
class text_with_stars : public text
{
public:
void show();
};
void text_with_stars::show()
{
cout << "*";
text::show();
cout << "*";
}
int main()
{
text* array[2];
array[0] = new text;
array[0]->write("Hello");
text_with_stars* pointer = new text_with_stars;
pointer->write("Hi");
array[1] = pointer;
for (int i=0;i<2;i++)
{
array[i]->show();
}
return 0;
}
But when I do this, the output is "HelloHi" meaning that the second object used the show version that is from text and not from text_with_stars, but I made it exactly the same way that the book described. What Is the problem??
Here is what is written in the book:
Question* quiz[2];
quiz[0] = new Question;
quiz[0]->set_text("Who was the inventor of C++?");
quiz[0]->set_answer("Bjarne Stroustrup");
ChoiceQuestion* cq_pointer = new ChoiceQuestion;
cq_pointer->set_text("In which country was the inventor of C++ born?")
cq_pointer->add_choice("Australia",false);
...
quiz[1] = cq_pointer;
The chapter right next to the one I was reading is about virtual functions and it explains that the system will always use the member functions of Question instead of ChoiceQuestion, looks like I should read more before asking questions on internet!
void show()
needs to be virtual in the base class if you want to use methods from derived classes from base class pointers
The reason this is happening is because the function you are calling is non-virtual.
Let's say we have a class Parent and a class Child inheriting from the parent:
class Parent {
public:
void f() {
cout << "Parent::f()" << endl;
}
};
class Child : public Parent {
public:
void f() {
cout << "Child::f()" << endl;
}
};
Now, let's make a pointer to a Parent and store a Child in it (polymorphism):
Parent *ptr = new Child;
ptr->f();
At this point, the compiler sees ptr having type Parent* and determines that the function to be called is Parent::f().
In order to call Child::f() when dealing with polymorphism? The Parent::f() must be defined virtual. The compiler then generates code to check at run-time the value that is stored in memory to call the appropriate (child) function.
In short: ONLY when a function is virtual and is called on a pointer or reference, a memory lookup is made to determine the actual type at that point in memory. Otherwise it is not.
Related
My question is related to C++. I have two families of classes: "Floor" and "Object". The first and the second family has a virtual method named "Enter" (which is called when an object enters the floor).
I wish to distinguish the behavior of "Enter" based on the sub-class of a "Floor" and "Object" respectively.
So I overload the method "Enter" with derived classes as the parameters. I have got code that works correctly, but requires two steps to call proper method, and would like to ask whether it can be done in one function call:
Edit: I updated the code (now full working example) with the potential solution. I have used a pointer to method with casting to retrieve proper overloaded method. This pointer is initialized in the constructors of the derived "Floor" classes.
#include <iostream>
using namespace std;
class Floor;
class Flagstone;
class Object
{
public:
virtual void Enter(Floor *f); /* Generic object enters generic floor */
virtual void Enter(Flagstone *fs); /* Generic object enters flagstone */
};
class Box : public Object
{
public:
void Enter(Floor *f);
void Enter(Flagstone *fs);
};
class Floor
{
public:
typedef void (Object::*enterPtr)(Floor *);
enterPtr enter; /* Pointer to method, initialized by constructor */
Floor(enterPtr enter) : enter(enter)
{
}
};
class Flagstone : public Floor
{
public:
/* Select proper overloaded function using casting */
Flagstone() : Floor((enterPtr)(void (Object:: *)(Flagstone *))&Object::Enter)
{
}
};
void Object::Enter(Floor *f)
{
cout << " Generic object enters generic floor" << endl;
}
void Object::Enter(Flagstone *fs)
{
cout << "Generic object enters flagstone" << endl;
}
void Box::Enter(Floor *f)
{
/* Box enters generic floor */
cout << "Box enters generic floor" << endl;
}
void Box::Enter(Flagstone *b)
{
/* Executed when a Box enters Flagstone: Correct */
cout << "Box enters Flagstone" << endl;
}
int main()
{
Floor *f = new Flagstone();
Object *o = new Box();
(o->*(f->enter))(f);
return 0;
}
Could I ask you to provide a minimum, reproducible example? Copying the code as is doesn't compile; indeed, there seems to be a circular dependency between the Floor and Object classes, as both rely on each other's implementation to be defined at all!
Both me and Nathan have tried to resolve this by forward-declaring the derived subtype 'Box', but this might be moot because:
you may want to invoke Box methods from Floor::Enter and Flagstone::Enter
the compiler throws an error for 'an undefined reference to a vtable', with answers here:
I agree with the others that Object::Enter(Flagstone*) seems redundant seems redundant given there exists Object::Enter(Floor*), which can resolve the dynamic type of the pointer passed-in
I ended up just realizing that the main() in this code could be actually a virtual Object or Floor method! Proper method will be called at first place and it will know one of the objects' true class.
So I cleaned the code. The function Enter(Floor *, Item *) just calls virtual method Floor::Enter() and it delegates the control to virtual method Item::Enter(), but now with addition to overloading.
The result method just reacts for the specific Floor and Item for example: Flagstone and Box incrementing the placed boxes counter.
This is very clean solution, however I can't make the methods inline as there is a cycle dependancy. But it's not a problem.
Here is the solution code:
#include <iostream>
using namespace std;
class Floor;
class Flagstone;
class Item
{
public:
/* Overload */
virtual void Enter(Floor *fl)
{
cout << "Item enters Floor." << endl;
}
virtual void Enter(Flagstone *fs)
{
cout << "Item enters Flagstone." << endl;
}
};
class Box : public Item
{
public:
static int count;
virtual void Enter(Floor *fl)
{
cout << "Box enters Floor." << endl;
}
virtual void Enter(Flagstone *fs)
{
cout << "Box enters Flagstone. Count++" << endl;
count++;
}
};
class Cherry : public Item
{
};
class Item;
class Floor
{
public:
/* Virtual Floor method. If object is in derived class,
it will call proper method. */
virtual void Enter(Item *it);
};
class Flagstone : public Floor
{
public:
virtual void Enter(Item *it);
};
class Wall : public Floor
{
};
/* Virtual Floor method. If object is in derived class, it will call proper method. */
void Floor::Enter(Item *it)
{
/* OK, we have Floor and Item or Item sub-class now we call item method, enter */
it->Enter(this);
}
void Flagstone::Enter(Item *it)
{
/* OK, we have Flagstone */
it->Enter(this);
}
int Box::count = 0;
void Enter(Floor *fl, Item *it)
{
fl->Enter(it);
}
int main(void)
{
Floor *fl = new Flagstone;
Item *it = new Box;
Enter(fl, it);
return 0;
}
I am enrolled in a C++ course, where i have the following code snippet:
class Pet {
protected:
string name;
public:
Pet(string n)
{
name = n;
}
void run()
{
cout << name << ": I'm running" << endl;
}
};
class Dog : public Pet {
public:
Dog(string n) : Pet(n) {};
void make_sound()
{
cout << name << ": Woof! Woof!" << endl;
}
};
class Cat : public Pet {
public:
Cat(string n) : Pet(n) {};
void make_sound()
{
cout << name << ": Meow! Meow!" << endl;
}
};
int main()
{
Pet *a_pet1 = new Cat("Tom");
Pet *a_pet2 = new Dog("Spike");
a_pet1 -> run();
// 'a_pet1 -> make_sound();' is not allowed here!
a_pet2 -> run();
// 'a_pet2 -> make_sound();' is not allowed here!
}
I'm not able to figure out why this is invalid. Please suggest suitable references for this that have ample explanation about why this is happening.
In C++, the types and names of variables at any point is what the compiler permits itself to know.
Each line of code is checked against the types and names of variables in the current scope.
When you have a pointer to a base class, the type of the variable remains pointer to the base class. The actual object it is pointing at could be a derived class, but the variable remains a pointer to the base class.
Pet *a_pet1 = new Cat("Tom");
a_pet1 -> run();
// 'a_pet1 -> make_sound();' is not allowed here!
the type of a_pet1 is Pet*. It may be pointing at an actual Cat object, but that is not information that the type of a_pet1 has.
On the next line, you are using a_pet1. You can only use it in ways that are valid for a Pet pointer on this line. a_pet1->make_sound() is not a valid operation on a Pet pointer, because the Pet type does not have a make_sound method.
You could do this:
Cat *a_pet1 = new Cat("Tom");
a_pet1 -> run();
a_pet1 -> make_sound(); // it now works!
because we changed the type of a_pet1 from Pet* to Cat*. Now the compiler permits itself to know that a_pet1 is a Cat, so calling Cat methods is allowed.
If you don't want to change the type of a_pet1 (which is a reasonable request), that means you want to support make_sound on a Pet, you have to add it to the type Pet:
class Pet {
protected:
string name;
public:
Pet(string n)
{
name = n;
}
void make_sound();
void run()
{
cout << name << ": I'm running" << endl;
}
};
now, a_pet1->make_sound() will be allowed. It will attempt to call Pet::make_sound, which is not Dog::make_sound, and as we didn't provide a definition for Pet::make_sound, this will result in an error at link time.
If you want Pet::make_sound to dispatch to its derived methods, you have to tell the compiler this is what you want. C++ will write the dispatch code for you if you use the virtual keyword properly, like this:
class Pet {
protected:
string name;
public:
Pet(string n)
{
name = n;
}
virtual void make_sound() = 0;
void run()
{
cout << name << ": I'm running" << endl;
}
};
here I both made make_sound virtual, and made it pure virtual. Making it virtual means that the compiler adds information to each Pet and Pet derived object so, when it is actually pointing to a derived object type and not a Pet, the caller can find the right derived method.
Pure virtual (the =0) simply tells the compiler that the base class method Pet::make_sound intentionally has no implementation, which also means that nobody is allowed to create a Pet, or a even Pet derived object instance, without providing a make_sound implementation for its actual type.
Finally, note that I mentioned "permits itself to know". The compiler limits what it knows at certain phases of compilation. Your statement that a_pet1 is a Pet* tells the compiler "I don't want you to assume this is a Cat, even though I put a Cat in there". At later stages of compilation, the compiler can remember that fact. Even at runtime, it is sometimes possible to determine the actual type of an object (using RTTI). The forgetting of the type of the object is both intentional and limited.
It turns out that "forced forgetting" is quite useful in a number of software engineering problems.
There are other languages where all method calls to all objects go through a dynamic dispatch system, and you never know if an object can accept a method call except by trying it at runtime. In such a language, calling make_sound on any object whatsoever would compile, and at runtime it would either fail or not depending on if the object actually has a make_sound method. C++ intentionally does not do this. There are ways to gain this capability, but they are relatively esoteric.
In your example a_pet1 and a_pet2 are pointers to objects of the 'Pet' class so your compiler only allows you to access functions that are actually available in that class. The 'Pet' class iteself does not contain a 'make_sound' function in this case. To fix this problem you can define a 'make_sound' function in the base class and mark it as 'virtual'. This will make a function call over a base pointer always invoke the execution of the according function in the inheriting class.
class Pet {
protected:
string name;
public:
Pet(string n)
{
name = n;
}
void run()
{
cout << name << ": I'm running" << endl;
}
virtual void make_sound() {}
};
class Dog : public Pet {
public:
Dog(string n) : Pet(n) {};
void make_sound() override
{
cout << name << ": Woof! Woof!" << endl;
}
};
class Cat : public Pet {
public:
Cat(string n) : Pet(n) {};
void make_sound() override
{
cout << name << ": Meow! Meow!" << endl;
}
};
int main()
{
Pet* a_pet1 = new Cat("Tom");
Pet* a_pet2 = new Dog("Spike");
a_pet1->run();
a_pet1->make_sound();
a_pet2->run();
a_pet2->make_sound();
}
We know that, derived class members functions can be accessed through a base class pointer in C++ , provided that these member functions have to be virtual. Is there a means to access derived class member functions which are NOT virtual or pure virtual from base class pointer.
i.e. I want to call derived class member functions which are present only in derived class & not in base class through base class pointer. How would I achieve this?
For example, if I design a factory design pattern,
class Vehicle {
public:
virtual void printVehicle() = 0;
static Vehicle* Create(VehicleType type);
};
class TwoWheeler : public Vehicle {
public:
void printVehicle() {
cout << "I am two wheeler" << endl;
}
void Some2WheelerONLYSpecificOPeration()
{
}
};
class ThreeWheeler : public Vehicle {
public:
void printVehicle() {
cout << "I am three wheeler" << endl;
}
void Some3WheelerONLYSpecificOPeration()
{
}
};
class FourWheeler : public Vehicle {
public:
void printVehicle() {
cout << "I am four wheeler" << endl;
}
void Some4WheelerONLYSpecificOPeration()
{
}
};
// Factory method to create objects of different types.
// Change is required only in this function to create a new object type
Vehicle* Vehicle::Create(VehicleType type) {
if (type == VT_TwoWheeler)
return new TwoWheeler();
else if (type == VT_ThreeWheeler)
return new ThreeWheeler();
else if (type == VT_FourWheeler)
return new FourWheeler();
else return NULL;
}
int main()
{
Vehicle* basePtr = Vehicle::Create(VT_TwoWheeler);
basePtr->Some2WheelerONLYSpecificOPeration(); //HOW TO ACHIEVE THIS CALL
basePtr = Vehicle::Create(VT_ThreeWheeler);
basePtr->Some3WheelerONLYSpecificOPeration(); //HOW TO ACHIEVE THIS CALL
basePtr = Vehicle::Create(VT_FourWheeler);
basePtr->Some4WheelerONLYSpecificOPeration(); // //HOW TO ACHIEVE THIS CALL
}
I want to call derived class member functions which are present only in derived class & not in base class through base class pointer. How would I achieve this ?
You cannot call a non-virtual member function of the derived class with a pointer to the base class.
You'll need a pointer to the derived class. The simplest method is to use dynamic_cast to get a pointer to the derived class, check whether the cast was successful, then call the derived class member function using a derived class pointer.
A better method would be to provide a virtual member function in the base class and implement it in the derived class.
You can do what you want with dynamic_cast, but this will lead to disappointing results at a code review. Instead, I pitch you go the same route you did with printVehicle
class Vehicle
{
public:
// without a virtual destructor you are walking into
// a very bad bug. The wrong destructor may be called.
virtual ~Vehicle()
{
}
virtual void printVehicle() = 0;
// Specific stuff that all children must provide
virtual void doTypeSpecificStuff() = 0;
// this is actually a bit of a ideological weird. I'm not sure I can call
// it a flaw. By making this factory function a member of Vehicle, Vehicle
// must now know its children. If this is the case, the VehicleType enum
// should probably be a member of Vehicle, but personally I think this
// factory should be a totally free function.
static Vehicle* Create(VehicleType type);
};
class TwoWheeler: public Vehicle
{
public:
void printVehicle()
{
cout << "I am two wheeler" << endl;
}
void doTypeSpecificStuff()
{
cout << "Doing two wheeler stuff" << endl;
}
};
Leaving out the other two classes and Vehicle::Create to save space.
int main()
{
Vehicle* basePtr = Vehicle::Create(VT_TwoWheeler);
basePtr->doTypeSpecificStuff(); //HOW TO ACHIEVE THIS CALL
// leaking memory here, so
delete basePtr;
// but also look into std::unique_ptr. Much better suited to this behaviour
}
In fact, let's act on on that final comment about std::unique_ptr right now. A unique_ptr manages your dynamic allocations for you so you don't have to clutter up your code with deletes and run the risk of missing one or deleteing too soon. The unique_ptr's pointer is valid for as long as the unique_ptr is in scope. If you can compile, the pointer is good unless you done something silly like never point it at anything or manually remove the pointer.
And while we're at it, let's eliminate my earlier concerns about vehicle::Create.
First we define a free function to replace Create and return a unique_ptr. Since I hate to have to have if (ptr != NULL) checks all through my code to make sure an object really was created, let's also make a big stink about it when we can't match the provided vehicle type with class by throwing an exception.
And rather than a chain of if-else ifs we'll use a somewhat more elegant switch statement.
std::unique_ptr<Vehicle> SmarterVehicleFactory(VehicleType type)
{
switch (type)
{
case VT_TwoWheeler:
return std::make_unique<TwoWheeler>();
case VT_ThreeWheeler:
return std::make_unique<ThreeWheeler>();
case VT_FourWheeler:
return std::make_unique<FourWheeler>();
default:
throw std::runtime_error("Invalid Vehicle type");
}
}
And then we'll use this new function
int main()
{
try
{
std::unique_ptr<Vehicle> basePtr = SmarterVehicleFactory(VT_TwoWheeler);
basePtr->doTypeSpecificStuff();
basePtr = SmarterVehicleFactory(VT_ThreeWheeler);
// unique_ptr freed the TwoWheeler for us.
basePtr->doTypeSpecificStuff();
basePtr = SmarterVehicleFactory(VT_FourWheeler);
basePtr->doTypeSpecificStuff();
// just for laughs we will ask for a FiveWheeler, which we have not yet
// fully implemented
basePtr = SmarterVehicleFactory(VT_FiveWheeler); // will throw exception
basePtr->doTypeSpecificStuff(); // will not be executed
}
catch (const std::exception & exc)
{
cerr << "Rats! Something bad happened: " << exc.what();
// basePtr will be unmodified and still pointing to a FourWheeler
}
} // basePtr will go out of scope here and clean up our memory for us.
The beauty of this approach is no class knows anything about any other class. You can put Vehicle in a header with the SmarterVehicleFactory prototype and the list of vehicle types and hide everything else. The user sees nothing. Everybody is kept in the dark.
Why is that good? Because now you can change any of the above classes, except the Vehicle interface class, without having any effect on any of the other classes. This makes your code easier to maintain and debug.
I'm trying to find the best way to use polymorphism without using inheritance, because I want to avoid virtual calls. I was looking for a way to improve what I currently have (with no avail) and I stumbled on this question. This is the best I can do so far:
template<class VehicleDetails>
class Vehicle {
VehicleDetails details;
public:
VehicleDetails& getDetails() {
return details;
}
const VehicleDetails& getDetails() const {
return details;
}
void printDetails() const {
details.printDetails();
}
}
class TwoWheeler {
public:
void printDetails() const {
cout << "I am two wheeler" << endl;
}
void specificTwoWheelerMethod() const {
cout << "I am specific functionality" << endl;
}
}
Then you use it as such:
Vehicle<TwoWheeler> vehicle;
vehicle.printDetails(); // prints "I am two wheeler"
Unfortunately this complicates things. Now every class/struct or function that takes a vehicle must be templated, unless you know the type of vehicle.
template<class VehicleDetails>
void doGeneralVehicleThings(const Vehicle<VehicleDetails>& vehicle) {
// ...
}
On the plus side when you do know the type you can access specific functionality via the getDetails() method without any casting or runtime overhead involved:
void doTwoWheelerThings(const Vehicle<TwoWheeler>& twoWheelerVehicle) {
twoWheelerVehicle.getDetails().specificTwoWheelerMethod(); // prints "I am specific functionality"
}
class game_list
{
public:
string name;
float price;
string platform;
string console;
string conditin;
bool is_portable;
};
class catridgeClass:public game_list
{
string N_bits;
bool is_import;
};
game list is dynamically created and a pointer called mainPointer points to that dynamic object. But I am confused on how to access cartridgeClasss elements through the parent class game_list. I already tried mainPointer->N_bits. Seems like it doesnt work that way? Sorry I am just a noob at c++.
To access catridgeClass attributes, you will need a catridgeClass object.
First, you need to correct your class to have public attributes.
class catridgeClass:public game_list
{
public:
string N_bits;
bool is_import;
};
class anotherClass: public game_list
{
public:
string other_member;
};
Than you need to get a catridgeClass object from the caller function:
int main()
{
std::vector<game_list *> games;
games.push_back(new catridgeClass);
games.push_back(new anotherClass);
for(int i=0; i<games.size(); i++)
{
//You will need to get a catridgeClass object to access it's members.
catridgeClass *catridge_ptr = dynamic_cast<catridgeClass *>(games[i]);
//Or to access anotherClass.
anotherClass *another_ptr = dynamic_cast<anotherClass*>(games[i]);
//If the conversion is not possible, dynamic_cast will return a null pointer
if(catridgeClass != NULL)
std::cout << catridge->N_bits << std::endln;
if(anotherClass != NULL)
std::cout << anotherClass->other_member << std::endln;
}
//And of course, you need to avoid a memory leak
for(int i=0; i<games.size(); i++)
delete games[i]
return 0;
}
Keep in mind that it's not a desired design. If you are trying to use polimorphism, is because all that classes share common behaviours. A better approach would be to use interfaces.
Try a virtual method getNBits() = 0; in parent class, and define it in child class.
See: C++ Virtual/Pure Virtual Explained
A parent class has no information about its child class. The only way to do what you want is to either cast like Dory suggested -- which I usually frown upon -- or to create a virtual function in the parent class that the child class redefines.
Why do I frown upon the cast? Most of the time dynamically casting an object to get data from it represents poorly written code. I'm not sure what the rest of your code looks like, but my guess is that there's a better way to write this via shared functionality. For example, let's say what you want to use these items for is displaying string information. In such a case, the best way to write it would be using virtual functions:
class game_list
{
public:
string name;
float price;
string platform;
string console;
string conditin;
bool is_portable;
public virtual void PrintInfo()
{
cout << "name: " << name << ", price: " << price; //etc
}
};
class catridgeClass:public game_list
{
string N_bits;
bool is_import;
public virtual void PrintInfo()
{
game_list::PrintInfo();
cout << ", bits: " << bits << ", is import: " << is_import;
}
};
Now calling mainPointer->PrintInfo() will print the correct information regardless of its underlying type. Much nicer, and it's the "Object-Oriented Way."
try to use dynamic_cast
catridgeClassPtr = dynamic_cast<catridgeClass*>(GameListPtr);
catridgeClassPtr->N_bits;
full info on dynamic_cast:
http://www.cplusplus.com/doc/tutorial/typecasting/
Suppose that I have the following structure of classes. I want to be able to determine of what class type the element in my Animal vector is, so that I may perform subclass-specific methods on it. The example below should demonstrate:
#include <iostream>
#include <vector>
using namespace std;
class Animal {
public:
int foodcount;
Animal() {
foodcount = 0;
cout << "An animal was created.\n";
}
virtual ~Animal() {
cout << "An animal was destroyed.\n";
}
};
class Lion : public Animal {
public:
Lion() {
cout << "A lion was created.\n";
}
virtual ~Lion() {
cout << "A lion was destroyed.\n";
}
void chowMeat(int howmuch) {
foodcount += howmuch;
}
};
class Butterfly : public Animal {
public:
Butterfly() {
cout << "A butterfly was created.\n";
}
virtual ~Butterfly() {
cout << "A butterfly was destroyed.\n";
}
void drinkNectar(int howmuch) {
foodcount += howmuch;
}
};
int main() {
Animal* A = new Lion();
Animal* B = new Butterfly();
vector<Animal*> v;
v.push_back(A);
v.push_back(B);
// a little later
for (int i=0; i<v.size(); i++) {
if (v[i] is a Lion) v[i]->chowMeat(); // will not work of course
if (v[i] is a Butterfly) v[i]->drinkNectar(); // will not work of course
}
std::cin.get();
return 0;
}
Obviously the marked code won't work, but how do I do what I want to do? Is there a workaround or a design principle that I should follow but am not? I've looked into dynamic_cast but understand that is unpretty. So how should I do it correctly?
In Java, I would do this:
if (v.get(i).getClass() == Lion.class) {
((Lion)v.get(i)).chowMeat();
}
if (v.get(i).getClass() == Butterfly.class) {
((Butterfly)v.get(i)).drinkNectar();
}
Ideally you would add a virtual function to the base class, void eat(int quantity) and override that function in the derived classes.
In this case, it might even make sense to make the function non-virtual and implement it in the base class, since both derived classes do the exact same thing.
Barring that, you can use dynamic_cast to test the dynamic type of the object:
if (Lion* lion = dynamic_cast<Lion*>(v[i])) {
lion->chowMeat(42);
}
else if (Butterfly* butterfly = dynamic_cast<Butterfly*>(v[i])) {
butterfly->drinkNectar(42);
}
// etc.
(On a different note, you'll want to be very careful using naked pointers in C++; it's very difficult to write correct code where you manage resources manually. In your example, you haven't freed the objects pointed to by A and B and have thus leaked them. Consider using smart pointers, like shared_ptr, to manage your resources automatically.)
What is the purpose of the loop? Is it to consume food? In that case, add a virtual void consumeFood(int howMuch) to your base class, and override that in your derived classes.
If the example is genuinely representative, a virtual function would solve your immediate problem much more neatly.
In any event, the simplest answer, if your classes have virtual functions, is to use dynamic_cast to check whether an object is of a given type. For example:
for (int i=0; i<v.size(); i++) {
if (Lion *lion = dynamic_cast<Lion *>(v[i]))
lion->chowMeat();
else if(Butterfly *butterfly = dynamic_cast<Butterfly *>(v[i]))
butterfly->drinkNectar();
}
It is built in to the language, and is just the thing for checking whether a pointer to base actually points to an object of a more derived type.
The other option is to have some kind of virtual GetType function in your base class, which you override per class to return something (an integer, an object, whatever) that uniquely identifies that class. Then you call this function at runtime, and examine the result to find out what sort of object is being pointed at.
dynamic_cast has the advantage of being built in to the language, and requires no effort on your part to support. Using one's own function has more predictable performance characteristics across a wide range of compilers and allows one to store data other than simply what type the object really is -- but you do have to write it all yourself.
Why not eat()?
class Animal {
public:
int foodcount;
Animal() {
foodcount = 0;
cout << "An animal was created.\n";
}
virtual ~Animal() {
cout << "An animal was destroyed.\n";
}
virtual void eat(int howMuch) {
foodcount += howmuch;
}
};
class Lion : public Animal {
public:
virtual void eat(int howmuch) {
Animal::eat(howmuch + 19);
}
};
class Butterfly : public Animal {
void eat(int howmuch) {
Animal::eat(howmuch / 1000);
}
};
class Tribble: public Animal
{
void eat(int howmuch) {
throw DontFeedTribles();
}
};
int main() {
std::auto_ptr<Animal> A = new Lion();
std::auto_ptr<Animal> B = new Butterfly();
vector<Animal*> menagerie;
menagerie.push_back(A.get());
menagerie.push_back(B.get());
BOOST_FOREACH(Animal* animal, menagerie)
{
animal->eat(10000);
}
std::cin.get();
return 0;
}