对虚函数C ++感到困惑

时间:2011-07-30 04:54:52

标签: c++ function virtual

我是一个c ++ n00b而且我不确定我是否找到了合适的地方,但我对此感到困惑:

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;
}

我的问题是为什么Monster或Ninja类中的attack()函数不被覆盖?任何帮助,甚至是链接,都将不胜感激。

5 个答案:

答案 0 :(得分:5)

只是做:

Enemy* n = new Ninja();
Enemy* m = new Monster();

n->sayHere();
n->attack();
m->sayHere();
m->attack();

delete n;
delete m;

那应该按照你的意愿去做。你需要使用指针才能工作。原因在于动态绑定的工作方式。

  

每当程序声明了C ++虚函数时,就会为该类构造一个v表。 v表包含类的虚函数的地址和派生类的每个对象的函数的指针。每当对c ++虚函数进行函数调用时,v-table用于解析函数地址。这是动态绑定在虚函数调用期间发生的方式。

这个想法是,编译器根据对象的内存地址存储指向每个方法的指针。它需要指针来访问表并调用适当的函数指针。想想你是否想编写一个OO版本的C,你会如何提供继承和多态这样的机制?当你这么想的时候,这是有道理的。

我刚刚读到你正在从JAVA转移。在JAVA中,大多数对象都存储在堆上。这一切都只是暗示。

JAVA的

Enemy n = new Ninja();
n.attack();

大致相当于

Enemy* n = new Ninja();
n->attack();

凡在哪里。 JAVA中的运算符更像是 - &gt; c ++中的运算符。在这两种情况下,n都在堆上。 Java只是隐藏了你的所有指针和内存管理。这就是为什么你可以对JAVA和C#中动态绑定的工作方式一无所知。

答案 1 :(得分:4)

这与您不通过指针访问敌人的事实有关:

    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;

答案 2 :(得分:2)

除非您通过指针或引用访问对象,否则虚函数调用将不起作用。为了使它工作,你需要重新编写你的敌人阵列

Enemy *enemies[2];
enemies[0] = &m;
enemies[1] = &n;

请注意,您必须将所有enemies[i].更改为enemies[i]->

答案 3 :(得分:1)

Enemy enemies[2];   
enemies[0] = m;    
enemies[1] = n;

这只是对象切片 - 只会复制派生对象中的Enemy个对象。虚拟功能无法发挥作用。

答案 4 :(得分:0)

这种现象称为object slicing