1

I'm confused about virtual functions. I was told that virtual in parent class means I can override it in child class. However if I omit the virtual in parent class, I'm still able to override it.

#include <iostream>
using namespace std;

class Enemy{
  public:
    //if I remove virtual, it still gets overriden in child class
  virtual void attack(){ 

    cout << "Attack Enemy!" << endl;
  }
};


class Minion : public Enemy {
  public:
  void attack(){
    cout << "Attack Minon!" << endl;
  }
};
int main() {
  Minion m;
  m.attack();
}
Jarod42
  • 203,559
  • 14
  • 181
  • 302
tomeda
  • 55
  • 1
  • 6

3 Answers3

3

If a function is virtual, the call is dynamically dispatched to the implementation provided by the derived type through the vtable at runtime, whereas without, the compiler looks at the object at compile time and selects the class-method of the static type. If you have a pointer to the base-class this means that the base-implementation is used, if the function is not virtual:

Enemy *e = new Minion(); e->attack();

will print "Attack Enemy!" if attack is not virtual. When using a virtual function, the compiler will insert some logic to lookup the right implementation at run-time, and, when e->attack() gets executed, look up the implementation in the vtable of the object pointer to by e, finding that Minion overrides attack, and thus printing "Attack Minion!".

If you want to force your derived classes to override the base-class method you can also make the function purely virtual by using

virtual void attack() = 0;

midor
  • 5,487
  • 2
  • 23
  • 52
1

You can override the method in question and ideally declare that with the override keyword to allow the compiler to complain when you aren't overriding anything.

class Enemy {
  public:
    virtual ~Enemy() = default; /* Don't forget... or non-virtual protected. */

    virtual void attack() {}
};

class Minion : public Enemy {
  public:
    void attack() override {}
};

Your confusion probably stems from the fact that you can equally well shadow the base class method.

class Enemy {
  public:
    virtual ~Enemy() = default;
    void attack() {}
};

class Minion : public Enemy {
  public:
    void attack() {}
};

This does not only do something different, it would in addition be an example for extraordinarily poor naming, as it's confusing to the reader: Equal member function names with identical signatures in the context of a class hierarchy are inevitably associated with overridden methods.

lubgr
  • 37,368
  • 3
  • 66
  • 117
0

You haven't overriden it, you have simply added another method with the same signature.

Enemy* enemy = new Minion();

enemy->attack();

delete enemy;

If this calls the code from Minion you did it right. If it calls the code from Enemy, you did something wrong. You will need virtual to do it right.

nvoigt
  • 75,013
  • 26
  • 93
  • 142