According to the C++20 Standard (Virtual functions [class.virtual])
1 A non-static member function is a virtual function if it is first
declared with the keyword virtual
or if it overrides a virtual
member function declared in a base class (see below).
and
2 If a virtual member function vf
is declared in a class Base
and in a
class Derived
, derived directly or indirectly from Base
, a member
function vf
with the same name, parameter-type-list ([dcl.fct]),
cv-qualification, and ref-qualifier (or absence of same) as Base::vf
is declared, then Derived::vf
overrides113 Base::vf
.
Pay attention to that even a virtual function can be hidden in some intermediate derived class nevertheless it can be overriden in a subsequent derived class.
That is if for example you will change your classes the following way
class parent
{
public:
virtual void f() { cout << "parent::f()" << endl; }
};
class child : public parent
{
public:
void f( int ) { cout << "child::f()" << endl; }
};
class grandchild : public child
{
public:
void f() { cout << "grandchild::f()" << endl; }
};
where the function f( int )
declared in the class child
hides the virtual function f()
declared in the class parent
nevertheless you can override it in the class grandchild
. The program output wll be the same as in the original program.
Here is a demonstration program.
#include <iostream>
using namespace std;
class parent
{
public:
virtual void f() { cout << "parent::f()" << endl; }
};
class child : public parent
{
public:
void f( int = 0 ) { cout << "child::f( int )" << endl; }
};
class grandchild : public child
{
public:
void f() { cout << "grandchild::f()" << endl; }
};
int main()
{
grandchild grandchild1;
parent *p = &grandchild1;
p->f();
child child1;
p = &child1;
p->f();
}
The program output is
grandchild::f()
parent::f()
Some remarks. For the class child
the final overrider of the virtual function, declared in the class parent
, is the function parent::f
. For the class grandchild
the final overrider is the function grandchild::f
.
It is better to use always the specifier override
in declarations of virtual functions as for example
class grandchild : public child
{
public:
void f() override { cout << "grandchild::f()" << endl; }
};
In this case your code will be more clear.