c++ virtual keyword vs overriding function

2019-06-16 16:50发布

问题:

I am learning c++ and am learning about the virtual keyword. I have scoured the internet trying to understand it to no avail. I went into my editor and did the following experiment, expecting it to print out the base message twice (because I was under the impression that the virtual keyword is needed to override functions). However, it printed out two different messages. Can someone explain to me why we need the virtual keyword if we can simply override functions and still seemingly get polymorphic behavior? Perhaps someone can help me and other people in the future understand virtual vs. overriding. (The output I am getting is "I am the base" followed by "I am the derived").

#include <iostream>

using namespace std;
class Base{
public:
    void printMe(){
        cout << "I am the base" << endl;
    }
};
class Derived: public Base{
public:
    void printMe(){
        cout << "I am the derived" << endl;
    }
};
int main() {
    Base a;
    Derived b;
    a.printMe();
    b.printMe();
    return 0;
}

回答1:

Consider the following example. The important line to illustrate the need for virtual and override is c->printMe();. Note that the type of c is Base*, however due to polymorphism it is correctly able to call the overridden method from the derived class.

#include <iostream>

class Base{
public:
    virtual void printMe(){
        std::cout << "I am the base" << std::endl;
    }
};

class Derived: public Base{
public:
    void printMe() override {
        std::cout << "I am the derived" << std::endl;
    }
};

int main() {
    Base a;
    Derived b;
    a.printMe();
    b.printMe();
    Base* c = &b;
    c->printMe();
    return 0;
}

The output is

I am the base
I am the derived
I am the derived


回答2:

With the code you have, if you do this

Derived derived;
Base* base_ptr = &derived;
base_ptr->printMe();

What do you think happens? It will not print out I am the derived because the method is not virtual, and the dispatch is done off the static type of the calling object (i.e. Base). If you change it to virtual the method that is called will depend on the dynamic type of the object and not the static type.



回答3:

You're not seeing the behaviour here because you've declared b to be of type Derived so the compiler knows what functions to use. In order to expose why virtual is necessary you need to mix things up:

int main() {
    Base a;
    Base *b = new Derived();

    a.printMe();
    b->printMe();

    delete b;

    return 0;
}

Now b is of type Base* which means it's going to use the functions on Base plus whatever's in the virtual function table. This breaks your implementation. You can fix it by properly declaring things virtual.



回答4:

override is a new keyword added in C++11.

You should use it because:

  • the compiler will check if a base class contains a matching virtual method. This is important since some typo in the method name or in its list of arguments (overloads are allowed) can lead to the impression that something was overridden when it really was not.

  • if you use override for one method, the compiler will report an error if another method is overridden without using the override keyword. This helps detect unwanted overrides when symbol collisions happen.

  • virtual doesn't mean "override". In class doent use "override" keyword than to override a method you can simply write this method omitting "virtual" keyword, override will happen implicitly. Developers were writing virtual before C++11 to indicate their intention of override. Simply put virtual means: this method can be overridden in a subclasses.