Reputation: 2353
I'm a c++ n00b and I'm not sure if I have looked in the right places but I'm confused about this:
include <iostream>
using namespace std;
class Enemy
{
public:
void sayHere()
{
cout<<"Here"<<endl;
}
virtual void attack()
{
}
};
class Monster: public Enemy
{
public:
virtual void attack()
{
cout<<"RAWR"<<endl;
}
};
class Ninja: public Enemy
{
public:
virtual void attack()
{
cout<<"Hiya!"<<endl;
}
};
int main()
{
Ninja n;
Monster m;
Enemy enemies[2];
enemies[0] = m;
enemies[1] = n;
for(int i = 0; i<2; i++)
{
enemies[i].sayHere();
enemies[i].attack();//Will not be overriden
}
return 0;
}
My question is why isn't the attack() function in the Monster or Ninja class being overriden? Any help, even a link, would be greatly appreciated.
Upvotes: 2
Views: 1091
Reputation: 8206
Just do:
Enemy* n = new Ninja();
Enemy* m = new Monster();
n->sayHere();
n->attack();
m->sayHere();
m->attack();
delete n;
delete m;
That should do as you want. You need to use pointers for it to work. The reason lies in the way dynamic binding works.
Whenever a program has a C++ virtual function declared, a v-table is constructed for the class. The v-table consists of addresses to the virtual functions for classes and pointers to the functions from each of the objects of the derived class. Whenever there is a function call made to the c++ virtual function, the v-table is used to resolve to the function address. This is how the Dynamic binding happens during a virtual function call.
The idea is, the compiler stores pointers to each method based on the memory address of the object. It needs the pointer to access the table and invoke the appropriate function pointer. Think about if you wanted to write an OO version of C, how would you supply such a mechanism as inheritance and polymorphism? It makes sense when you think of it that way.
I just read that you are moving over from JAVA. In JAVA, most of your objects are stored on the heap. It is all just implied.
JAVA's
Enemy n = new Ninja();
n.attack();
is roughly equivalent to
Enemy* n = new Ninja();
n->attack();
Where the . operator in JAVA is more like the -> operator in c++. In both cases, n is on the heap. Java just hides all of the pointer and memory management stuff from you. This is why you can have blissful ignorance of the way dynamic binding works in JAVA and C#.
Upvotes: 5
Reputation: 7095
Unless you access an object through a pointer or reference, virtual function calls will not work. To get it to work, you'll need to re-write your enemies array as
Enemy *enemies[2];
enemies[0] = &m;
enemies[1] = &n;
Note that you would have to change all enemies[i].
to enemies[i]->
.
Upvotes: 2
Reputation: 28806
This has to do with the fact that you don't access your enemies through pointers:
Ninja n;
Monster m;
Enemy *enemies[2];
enemies[0] = &m;
enemies[1] = &n;
for (int i = 0; i < 2; i++)
{
enemies[i]->sayHere();
enemies[i]->attack();
}
return 0;
Upvotes: 4
Reputation: 18411
Enemy enemies[2];
enemies[0] = m;
enemies[1] = n;
This is just object slicing - only Enemy
object from derived objects will be copied. Virtual functions cannot play role.
Upvotes: 1