对虚拟函数 C++ 感到困惑

发布于 2024-11-26 23:35:57 字数 889 浏览 0 评论 0原文

我是一个 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() 函数没有被覆盖?任何帮助,甚至是链接,将不胜感激。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

躲猫猫 2024-12-03 23:35:57

Just do:

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 表来解析函数地址。这就是动态绑定在虚拟函数调用期间发生的方式。

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

我刚刚读到您要从 JAVA 转过来。在JAVA中,大部分对象都存储在堆上。这一切都只是暗示而已。

JAVA的

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

大致相当于

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

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

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#.

-柠檬树下少年和吉他 2024-12-03 23:35:57

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

    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;

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;
浅紫色的梦幻 2024-12-03 23:35:57

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

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

注意,你必须将所有 enemies[i]. 更改为 enemies[i]->< /代码>。

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]->.

帅气称霸 2024-12-03 23:35:57
Enemy enemies[2];   
enemies[0] = m;    
enemies[1] = n;

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

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.

长梦不多时 2024-12-03 23:35:57

这种现象称为对象切片

The phenomenon is called object slicing.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文