Recently I am reading java. Because Java is bound at runtime, I mentioned an interesting problem, that is, running virtual functions in constructors.
Can a virtual function be run in a constructor? We will not discuss whether this is necessary in the actual project (at least I have not met it yet, maybe there are other solutions even if I have met it .), Perform some analysis when calling a virtual function in a single constructor.
In Java, if a virtual function is called in the constructor, it can be compiled without running errors, but the running result may not be what you want. In Java, the virtual function executed by the constructor will be a function in the classes Class (if the classes override the virtual function ), but here we have doubts. The constructor is built from the parent class, that is, the struct class has not yet been constructed. Therefore, if the functions of the struct class are executed at this time, it is undoubtedly insecure. Therefore, there is no problem in Java.
Will the situation be the same in VC ++? I was curious, so I did the test.
First, we use the following code to test:
# Include "stdafx. H "</P> <p> class virclassa <br/>{< br/> Public: <br/> virclassa () {<br/> printf ("virclassa construct before/R/N"); <br/> FUNA (); <br/> printf ("virclassa construct after/R/N"); <br/>}< br/> virtualvoid FUNA () {<br/> printf ("virclassa FUNA/R/N"); <br/>}< br/>}; </P> <p> class virclassb: public virclassa <br/>{< br/> Public: <br/> virclassb () {<br/> printf ("virclassb construct before/R/N "); <br/> FUNA (); <br/> printf ("virclassb construct after/R/N"); <br/>}< br/> virtualvoid FUNA () {<br/> printf ("virclassb FUNA/R/N"); <br/>}< br/> }; </P> <p> int _ tmain (INT argc, _ tchar * argv []) <br/>{< br/> virclassb; </P> <p> virclassb * pb = & A; <br/> virclassa * pA = Pb; </P> <p> printf ("Pb-> FUNA () before/R/N "); <br/> Pb-> FUNA (); </P> <p> printf (" Pa-> FUNA () before/R/N "); <br/> pa-> FUNA (); <br/> getchar (); <br/> return 0; <br/>}
The running result of the above Code is as follows:
We can see that the implementation method of VC ++ is different from that of Java. When constructing object A, although the object is of the virclassb type, however, although the virclassa constructor of the parent class calls a virtual function and the virtual function is overwritten by virclassb, FUNA in virclassa is actually called, which is also justified, although the final object to be constructed belongs to virclassb, it still belongs to virclassa at this moment, so it is reasonable to call the FUNA of virclassa. This is certainly more scientific than Java, at least there will be no inexplicable errors in Java.
After the build is complete, the execution of the virtual function returns to normal. The results of the subsequent two operations are virclassb FUNA.
In fact, we can see from the source code that the pointer assignment of the virtual function table occurs in the constructor, and before the constructor is executed, it is not difficult to explain the above results.
But I still don't want to stop it, because we should not ignore another situation, that is, pure virtual functions. See the following code:
# Include "stdafx. H "</P> <p> class virclassa <br/>{< br/> Public: <br/> virclassa () {<br/> printf ("virclassa construct before/R/N"); <br/> FUNA (); <br/> printf ("virclassa construct after/R/N"); <br/>}< br/> virtualvoid FUNA () = 0; <br/> }; </P> <p> class virclassb: Public virclassa <br/>{< br/> Public: <br/> virclassb () {<br/> printf ("virclassb construct before/R/N"); <br/> FUNA (); <br/> printf ("virclassb construct after/R/N"); <br/>}< br/> virtualvoid FUNA () {<br/> printf ("virclassb FUNA/R/N"); <br/>}< br/> }; </P> <p> int _ tmain (INT argc, _ tchar * argv []) <br/>{< br/> virclassb; </P> <p> virclassb * pb = & A; <br/> virclassa * pA = Pb; </P> <p> printf ("Pb-> FUNA () before/R/N "); <br/> Pb-> FUNA (); </P> <p> printf (" Pa-> FUNA () before/R/N "); <br/> pa-> FUNA (); <br/> getchar (); <br/> return 0; <br/>}
We can change the virclassa code FUNA to a pure virtual function and call it in the virclassa constructor. Is this also true for programming? Because pure virtual functions are originally used for the coverage class, they can be called in the parent class. Let's start compiling and running.
Oh ?~! A compilation error occurs.
The external symbol "public: Virtual void _ thiscall virclassa: FUNA (void )"(? FUNA @ virclassa @ uaexxz). This symbol is used in the function "public: _ thiscall virclassa: virclassa (void )"(?? 0virclassa @ Qae @ xz) is referenced
Wow! Wonder how clever the compiler is! Because the constructor calls FUNA in virclassa, as mentioned above. Since you have not defined it, we should give a compilation error. Here, the VC ++ compiler is trustworthy.
Let's take another test example.
# Include "stdafx. H "</P> <p> class virclassa <br/>{< br/> Public: <br/> virclassa () {<br/> printf ("virclassa construct before/R/N"); <br/> FUNA (); <br/> printf ("virclassa construct after/R/N"); <br/>}< br/> virtualvoid FUNA () {<br/> printf ("virclassa FUNA/R/N"); <br/> funb (); <br/>}< br/> virtual void funb () = 0; <br/>}; </P> <p> class virclassb: Public virclassa <br/>{< br/> Public: <br/> virclassb () {<br/> printf ("virclassb construct before/R/N"); <br/> FUNA (); <br/> printf ("virclassb construct after/R/N"); <br/>}< br/> virtualvoid FUNA () {<br/> printf ("virclassb FUNA/R/N"); <br/>}< br/> virtualvoid funb () {<br/> printf ("virclassb funb/R/N"); <br/>}< br/> }; </P> <p> int _ tmain (INT argc, _ tchar * argv []) <br/>{< br/> virclassb; </P> <p> virclassb * pb = & A; <br/> virclassa * pA = Pb; </P> <p> printf ("Pb-> FUNA () before/R/N "); <br/> Pb-> FUNA (); </P> <p> printf (" Pa-> FUNA () before/R/N "); <br/> pa-> FUNA (); <br/> getchar (); <br/> return 0; <br/>}
You can test this example to see what is going on? That's right. The program will crash.
An error occurred during runtime:
You can see that the function funb () is called in FUNA. A pure virtual function call runtime error will occur.
Therefore, the compiler cannot identify purely virtual function calls in constructor. Fortunately, there is another runtime error, which is better than Java. Because we know that Java will cause some difficult-to-recognize errors.
Therefore, through the above analysis, it is recommended that you do not call virtual functions in the constructor, and the program master recommends that the constructor do as simple as possible. Compared with Java, VC ++ should be safer.