c++ non virtual function acts like virtual function

Viewed 153

Probably, i misunderstood c++ polymorphism(virtual function). Please point me what i miss.

the source code is below


#include <iostream>

using namespace std;

class A {
    public:
        virtual void print(void) {
            cout<<"class A"<<endl;
        }
};

class B : public A {
    public:
        void print(void) {
            cout<<"class B"<<endl;
        }
};

class C : public B {
    public:
        void print(void) {
            cout<<"class C"<<endl;
        }
};

int main() {
    A a;
    B b;
    C c;
    A *pAa = &a;
    A *pAb = &b;
    A *pAc = &c;
    B *pBc = &c;

    pAa->print();
    pAb->print();
    pAc->print();
    pBc->print();                   // shouldn't be "class B"

    return 0;
}

result

------------------------------
class A
class B
class C
class C                             // shouldn't be "class B"

my understanding is that the last print statement should print "class B" because pBc is a pointer of class B and the print function in class B is non virtual member function. i could not find the answer about this situation.

please tell me why or point me where i can find the answer and understand c++ polymorphism in comprehension. thanks.

2 Answers

the print function in class B is non virtual member function

No. Since A::print is marked as virtual and B inherits from A, then B::print is virtual too; regardless of the keywork virtual is specified on it or not.

(emphasis mine)

If some member function vf is declared as virtual in a class Base, and some class Derived, which is derived, directly or indirectly, from Base, has a declaration for member function with the same

  • name
  • parameter type list (but not the return type)
  • cv-qualifiers
  • ref-qualifiers

Then this function in the class Derived is also virtual (whether or not the keyword virtual is used in its declaration) and overrides Base::vf (whether or not the word override is used in its declaration).

If a function with a given signature is declared as virtual in a top-level base class, then the function is virtual in all derived classes no matter if it is marked with the keyword virtual (override, final) or not:

virtual function specifier

Then this function in the class Derived is also virtual (whether or not the keyword virtual is used in its declaration)

struct Base {
    // Pure virtual function.
    virtual void foo() const = 0;  
};

struct A : public Base {
    // Overriding virtual function, even if it 
    // is not marked as virtual (override, or final).
    void foo() const {}   
};

In A, adding the virtual specifier to foo() would only bring semantic value; it will be no functional difference whether virtual is omitted or not (unless someone changes the interface in Base).


Many static analyzers enforce(1) marking derived virtual functions with override or final, for two reasons:

  • semantics; clearly showing the given function is a virtual function (as per being defined so higher up in the inheritance chain), and
  • enforcement; if a function is marked as override and final but is not actually an overriding function, you will get a compiler error, which can be particularly useful to protect against mistakes when changing a base class interface (whilst forgetting which classes that actually implements this interface).

E.g.:

struct Base {
    // Pure virtual function.
    virtual void foo() const = 0;  
};

struct A : public Base {
    // Overriding virtual function.
    void foo() const override {}   
};

struct B final : public Base {
    // Overriding (final) virtual function.
    void foo() const final {}

    // Error: Function does not override.
    // void bar() const override {}
};

(1) E.g. Rule A10-3-1 in the Autsar C++14 Language Guidelines (safety-critical development in automotive) is categorized as a required rule: Virtual function declaration shall contain exactly one of the three specifiers:(1) virtual, (2) override, (3) final.

Related