Virtual keyword confusion in C ++

I studied the effects of the virtual 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(); } 

Expected Result:

 B C B 

Since the show function in B is not virtual. But the result when compiling:

 B C C 

It behaves as if the show function in B was virtual. Why is this so? Is class B canceled here? Why do I point to class A if I point to class C to class B?

+5
source share
3 answers

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 .

 #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

 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

 #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(); } 
+7
source

You do not need to specify the function as virtual in the derived class if it is specified in the base class.

+7
source

The behavior is correct. Since the show function is virtual, this version is called, which will be bound to the instance to which you call it, and not to the type specified by the type of this instance (which may be the base of this real type of the instance).

0
source

Source: https://habr.com/ru/post/1273239/


All Articles