GURU Of THE WEEK Terms 05: overwriting virtual functions

zhaozj2021-02-08  357

Gotw # 05 Overriding Virtual Functions

Author: Herb Sutter

Translation: Kingofark

[Declaration]: This article takes the Guru of The Week column on www.gotw.ca website, and its copyright belongs to the original person. Translator Kingofark translated this article without the consent of the original person. This translation is only for self-study and reference, please read this article, do not reprint, spread this translation; people download this translation content, please delete its backup immediately after reading. Translator Kingofark is not responsible for people who violate the above two principles. This declaration.

Revision 1.0

GURU Of THE WEEK Terms 05: overwriting virtual functions

Difficulty: 6/10

(Virtual Function is really a basic characteristic, right? Ok, if you can answer the following questions, you will find that they are really cold, cold, bones.)

[problem]

When you swim the company's archive code in a dusty corner, you discovered a section of the following procedure written in the unnamed. This unnamed programmer seems to have tried to do test with this program to see the operation of certain C characteristics. Do you know what results do this programmers want to print after running? Do you know the actual results after the program run?

#include

#include

Using namespace std;

Class base {

PUBLIC:

Virtual void f (int) {

Cout << "Base :: f (int) << endl;

}

Virtual void f (double) {

Cout << "Base :: f (double" << Endl;

}

Virtual Void G (INT i = 10) {

COUT << i << endl;

}

}

Class Derived: public base {

PUBLIC:

Void F (Complex ) {

Cout << "Derived :: F (Complex) << Endl;

}

Void G (INT i = 20) {

Cout << "Derived :: g () << i << endl;

}

}

Void main () {

Base B;

Derived D;

Base * pb = new deerid;

B.F (1.0);

D.f (1.0);

Pb-> f (1.0);

B.G ();

D.G ();

PB-> g ();

Delete PB;

}

[answer]

First, let's talk about the problem of coding style:

1. void main ()

This is not a legitimate main statement, although many compilers allow this way of writing. "Int main ()" or "int main (int Argc, char * argv []) should be used.

However, in fact, you still don't need to add any return statements (although sometimes adding the return statement is to form a good coding style that is incorrectly reported to the external caller). In fact, if the main does not return a statement, its effect is equivalent to executing "returnography;".

2. Delete PB;

This looks like neither pollution and no nature - of course, premise is that Base's writer provides a virtual destructor. However, as we see in this program, in the case where there is no virtual destructor, it deletes the operation to the base class, which is an evil crime, and it is also a childish and simple. - Since then, the collapse is the best thing you can expect. [Rules]: Statement of the destructor (Virtual Destructor) of the base class as Virtual.

3. Derived :: f (Complex )

Derived is not overloaded Base :: F, but hides it. This details are very important, because this means in Derived, Base :: F (int) and base :: f (double) are invisible! (Not to mention that some popular compilers do not give a warning message on this situation.)

[Rule]: When the function in the derive class is the same name in the base class, and you don't want to hide these base class functions in the derived class, please use the USING declaration to set them within scope. .

4. Derived :: g (INT i = 10)

Unless you deliberately want to make others confused, don't change the default parameters of the override inherited inherit. (Generally, overwriting without using parameter default is not a bad idea, but that is its own problem.) Yes, this is a legal and reasonable C statement; good, its results are also very good Definition; however, not, please don't do this. Looking down, you will find how it is confused.

[Rules]: Never change the inheritance function of overwriting (Overridden Inherited Function)

Ok, let us not talk about the trivial matters of the coded style. Now let's take a look at the main program to operate in the way that the unnamed programmer is expected.

Void main () {

Base B;

Derived D;

Base * pb = new deerid;

* B.F (1.0);

No problem, call Base :: f (double).

* D.f (1.0);

This statement calls derived :: f (Complex ). why? As mentioned above, there is no statement "use :: f;" in Derived, Base :: F (int) and base :: f (double) cannot be called.

Mr. Omnamble may have originally wanted to call Base :: f (double), but he even a compilation error message did not even, because luck is (?), Complex contains an implicit from Double Conversion (*), so the compiler looks it as Derived :: F (Complex (1.0)).

(*) Note: In the existing draft C standard, conversion constructor is not explicit (Explicit). * Pb-> f (1.0);

Interesting things happened here: Although Base * Pb points to a deerived object, but this statement is still called Base :: F (Double) because the overload resolution will be static (here, it refers to Base) Complete, not based on dynamic types (here you refer to Derived).

* B.G ();

This statement is just a simple print "10" because it causes a call to Base :: g (int), and its function parameters defaults to 10. This is nothing strange.

* D.G ();

This statement prints "Derived :: g () 20" because it causes call to Derived :: g (int), with the default value of 20. This is nothing strange.

* Pb-> g ();

This statement prints "Derived :: g () 10". This result may temporarily kill your mental brakes, leading to your sputum to enter a state of mental stagnation - until you realize that the compiler is not normal (although our poor unnamed is no doubt The should be shot). To remember, determine the default parameters and overload, is done with the static type of the object (herein it refers to the base), so the default value is selected. However, the function is just Virtual, so the actually called the function depends on the dynamic type of the object (here is Derived).

Finally, if you can understand the rest of the statement (although you will say: "!"), Then you can finally understand what I said "cold, cold, cold and bones". congratulations!

* Delete PB;

}

Delete the operation, of course, there will be some things that are only cleared, making the memory become unpredictable ... Take a look at the narrative about the virtual destructor in front.

转载请注明原文地址:https://www.9cbs.com/read-347.html

New Post(0)