使用虚拟和不使用虚拟的差异

num*_*l25 3 visual-c++

可能重复:
覆盖与虚拟

在C++中,无论您是否选择使用虚拟,您仍然可以覆盖基类功能.以下编译就好了......

class Enemy 
{
public:
    void SelectAnimation();
    void RunAI();
    void Interact()
    {
        cout<<"Hi I am a regular Enemy";
    }

private:
    int m_iHitPoints;
};

class Boss : public Enemy
{
public:
    void Interact()
    {
        cout<<"Hi I am a evil Boss";
    }
};
Run Code Online (Sandbox Code Playgroud)

所以我的问题是使用或不使用虚函数有什么区别.而且缺点是什么.

小智 18

如果你有代码:

Enemy * p = new Boss;
p->Interact();
Run Code Online (Sandbox Code Playgroud)

并且Interact不是虚拟的,你会得到Enemy的Interact.换句话说,将根据明显而不是正在调用的事物的实际类型来选择函数.这几乎不是您想要的,所以如果您打算通过基指针调用方法(例如,如果您在向量或列表中有一组基本指针),那么该函数应该在基类中变为虚拟.您还需要将此类基类的析构函数设置为虚拟,以便通过基本指针删除实例时的行为是明确定义的.

  • @Omnifarious:`virtual`在内存和函数调用开销方面都有一个小的间接惩罚.在大多数实现中,它归结为一个额外的指针取消引用到一个小的调用表中.在某些情况下,这种开销可能是不合需要的或者是禁止的,因此如果您不需要,则没有理由必须支付这笔开销. (2认同)

Jam*_*lis 6

如果Enemy::Interact()未声明virtual,Enemy::Interact()则从基类中的成员函数或通过指向基类的引用调用将不会调用派生类Interact()函数.

例如:

Boss boss;
Enemy* bossEnemy = &boss;

boss.Interact();       // calls Boss::Interact()
bossEnemy->Interact(); // calls Enemy::Interact()
Run Code Online (Sandbox Code Playgroud)

如果你声明Enemy::Interact()virtual,那么Boss::Interact()将按照你的预期被调用.

使用虚函数的缺点是它们可能比非虚函数更昂贵.不使用虚函数的缺点是您可能无法获得所需的结果.