C++ Overriding method not working

2019-03-04 17:14发布

问题:

I am expecting "My Game" to print out but I am getting "Base" This only happens when using methods internally inside the class.

#include <iostream>

namespace Monster { class App {
public:
  App(){}
  ~App(){}
  void run(){
    this->speak();
  }
  void speak(){
    std::cout << "Base" << "\n";
  };
};}; // class / namespace

class MyGame : public Monster::App {
public:
  MyGame(){}
  ~MyGame(){}
  void speak(){
    std::cout << "My Game" << "\n";
  };
};

int main(){
  MyGame *child = new MyGame;
  child->run();
  return 0;
}

回答1:

In C++ you need to specifically declare a function to be virtual:

class BaseClass {
    virtual void speak () {
        ...
    }
};


回答2:

In C++ a method can only be overridden if it was marked virtual. You can think of virtual as a synonym for "overridable".

The virtual keyword has to appear in the base class. It may also appear optionally in the subclasses at the point of override, but it does not have to.

If you are using a compiler that supports C++11 (and you should if you are learning C++), I recommend that you always use the new override keyword when you mean to override:

class Base {
public:
    virtual void speak() {
        std::cout << "Base";
    }
};

class Derived : public Base {
public:
    void speak() override {  // <---
        std::cout << "Derived";
    }
};

If the method isn't actually an override, the compiler will tell you so by giving an error.

It is not always obvious on the first read whether a method is an override. For example the following is correct thanks to return type covariance:

class A {};
class B : public A {};

class Base {
public:
    virtual A* foo() {
        return nullptr;
    }
};

class Derived : public Base {
public:
    B* foo() override {
        return nullptr;
    }
};

This might not be useful very often, but override makes it clear in case someone has to read it.

Also, if you have at least one virtual method in your class, also make its destructor virtual. This will assure that all the destructors will run when needed and things get cleaned up properly:

class App {
public:
    App() {}
    virtual ~App() {}  // <---
    void run() {
        this->speak();
    }
    virtual void speak() {
        std::cout << "Base\n";
    };
};