Virtual/pure virtual explained

后端 未结 12 1452
暖寄归人
暖寄归人 2020-11-22 01:31

What exactly does it mean if a function is defined as virtual and is that the same as pure virtual?

12条回答
  •  迷失自我
    2020-11-22 02:30

    I'd like to comment on Wikipedia's definition of virtual, as repeated by several here. [At the time this answer was written,] Wikipedia defined a virtual method as one that can be overridden in subclasses. [Fortunately, Wikipedia has been edited since, and it now explains this correctly.] That is incorrect: any method, not just virtual ones, can be overridden in subclasses. What virtual does is to give you polymorphism, that is, the ability to select at run-time the most-derived override of a method.

    Consider the following code:

    #include 
    using namespace std;
    
    class Base {
    public:
        void NonVirtual() {
            cout << "Base NonVirtual called.\n";
        }
        virtual void Virtual() {
            cout << "Base Virtual called.\n";
        }
    };
    class Derived : public Base {
    public:
        void NonVirtual() {
            cout << "Derived NonVirtual called.\n";
        }
        void Virtual() {
            cout << "Derived Virtual called.\n";
        }
    };
    
    int main() {
        Base* bBase = new Base();
        Base* bDerived = new Derived();
    
        bBase->NonVirtual();
        bBase->Virtual();
        bDerived->NonVirtual();
        bDerived->Virtual();
    }
    

    What is the output of this program?

    Base NonVirtual called.
    Base Virtual called.
    Base NonVirtual called.
    Derived Virtual called.
    

    Derived overrides every method of Base: not just the virtual one, but also the non-virtual.

    We see that when you have a Base-pointer-to-Derived (bDerived), calling NonVirtual calls the Base class implementation. This is resolved at compile-time: the compiler sees that bDerived is a Base*, that NonVirtual is not virtual, so it does the resolution on class Base.

    However, calling Virtual calls the Derived class implementation. Because of the keyword virtual, the selection of the method happens at run-time, not compile-time. What happens here at compile-time is that the compiler sees that this is a Base*, and that it's calling a virtual method, so it insert a call to the vtable instead of class Base. This vtable is instantiated at run-time, hence the run-time resolution to the most-derived override.

    I hope this wasn't too confusing. In short, any method can be overridden, but only virtual methods give you polymorphism, that is, run-time selection of the most derived override. In practice, however, overriding a non-virtual method is considered bad practice and rarely used, so many people (including whoever wrote that Wikipedia article) think that only virtual methods can be overridden.

提交回复
热议问题