According to C ++ 2017 standard (function specifiers 10.1.2)
2 The virtual specifier should only be used in the initial declaration of a non-static class function; see 13.3.
AND (13.3 Virtual Functions)
2 If the virtual member function vf is declared in the Base class and in the Derived class obtained directly or indirectly from Base, the member is the vf function with the same name, list-type-list (11.3.5), cv-qualification and ref- qualifier (or lack of the same) as Base :: vf, then Derived :: vf is also virtual (regardless of what is declared), and it overrides 111 Base :: vf. . For convenience, we say that any virtual function redefines itself. A virtual member function C :: vf of an object of class S is a finite redefinition if only the most derived class (4.5), of which S is a subobject of the base class (if any), declares or inherits another member function that overrides vf. In a derived class, if a virtual member function in a subobject of a base class has more than one final interceptor, the program is poorly formed.
Thus, the show function in class B is a virtual function because it has the same signature as the function declared in class A
Consider a more interesting example when the class determinant const added to the member function show .
In this case, the output will look like
ACB
In this expression, the expressions
ab->show();
called the virtual function show , declared in class A
In this statement
ac->show();
the same virtual function is called that is overridden in class C The compiler uses the declaration of a virtual function in class A because the static pointer type ac is A * .
In this statement
bc->show();
it does not call a virtual member function show with the qualifier const , because the static pointer type bc is B * , and the compiler finds a function in class B that hides the virtual function declared in class A
For the source program, you can use the override specifier to make class definitions more understandable. for instance