Reputation: 125
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?
Upvotes: 6
Views: 1001
Reputation: 310920
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();
}
Upvotes: 7
Reputation: 8781
The behaviour is the correct one. Since the show
function is virtual, the version invoked will be the one attached to the instance you're calling it on, rather than the one described by the type of that instance (which can be a base of that instance's real type).
Upvotes: 0
Reputation: 7542
You don't need to specify a function as virtual
in derived class, if specified in the base
class.
Upvotes: 7