I was studying on effects of virtual
keyword in C++ and I came up with this code.
#include<iostream>
using namespace std;
class A {
public:
virtual void show(){
cout << "A \n";
}
};
class B : public A {
public:
void show(){
cout << "B \n";
}
};
class C : public B {
public:
void show(){
cout << "C \n";
}
};
int main(){
A *ab = new B;
A *ac = new C;
B *bc = new C;
ab->show();
ac->show();
bc->show();
}
The expected output is:
B
C
B
Since show
function in B is non-virtual. But the outcome when you compile this is:
B
C
C
It behaves as if show
function in B is virtual. Why is this the case? Does B class gets overridden here? How come I point to the A class if I'm pointing a C class to the B class?
According to the C++ 2017 Standard (10.1.2 Function specifiers)
2 The virtual specifier shall be used only in the initial declaration of a non-static class member function; see 13.3.
And (13.3 Virtual functions)
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 (11.3.5), cv-qualification, and ref-qualifier (or absence of same) as Base::vf is declared, then Derived::vf is also virtual (whether or not it is so declared) and it overrides111 Base::vf. For convenience we say that any virtual function overrides itself. A virtual member function C::vf of a class object S is a final overrider unless the most derived class (4.5) of which S is a base class subobject (if any) declares or inherits another member function that overrides vf. In a derived class, if a virtual member function of a base class subobject has more than one final overrider the program is ill-formed.
Thus the function show
in the class B
is a virtual function because it has the same signature as the function declared in the class A
.
Consider a more interesting example when in the class B
there is added the qualifier const
to the member function show
.
#include<iostream>
using namespace std;
class A {
public:
virtual void show(){
cout << "A \n";
}
};
class B : public A {
public:
void show() const{
cout << "B \n";
}
};
class C : public B {
public:
void show() {
cout << "C \n";
}
};
int main(){
A *ab = new B;
A *ac = new C;
B *bc = new C;
ab->show();
ac->show();
bc->show();
}
In this case the output will look like
A
C
B
In this expression statement
ab->show();
there is called the virtual function show
declared in the class A
.
In this statement
ac->show();
there is called the same virtual function that is overridden in the class C
. The compier uses the virtual function declaration in the class A because the static type of the pointer ac
is A *
.
In this statement
bc->show();
there is called non-virtual member function show
with the qualifier const
because the static type of the pointer bc
is B *
and the compiler finds the function in the class B
that hides the virtual function declared in the class A
..
For the original program you could use the specifier override
to make the class definitions more clear. For example
#include<iostream>
using namespace std;
class A {
public:
virtual void show(){
cout << "A \n";
}
};
class B : public A {
public:
void show() override{
cout << "B \n";
}
};
class C : public B {
public:
void show() override{
cout << "C \n";
}
};
int main(){
A *ab = new B;
A *ac = new C;
B *bc = new C;
ab->show();
ac->show();
bc->show();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With