Do not call the virtual function __ function in constructors and destructors

Source: Internet
Author: User

Read effective C + + Bar 歀 09: Virtual functions are never invoked during construction and destructor (Never call virtual functions during construction or destruction)

First, we use a phrase that is popular with programmers as the beginning of this article: if you call a virtual function in the constructor of a base class, the virtual function behaves like a "real" function during the base class construction.

During the base class partial construction of a derived class object, the type of the object is base class, not derived class. At this point, not only virtual functions will be resolved by the compiler to the base type, even the typeid and dynamic_cast in Rtti will treat the object as the base type. The C + + standard and compiler's reason for doing so is simple: during the base class partial construction of a derived class object, the exclusive component of the derived class has not been initialized, so the safest way to face them is to treat them as non-existent. A derived class object is not treated as a derived class object, but rather as a base class object, before its own constructor begins executing.


The same is true for destructors. Once the destructor of the derived class has finished executing, a member variable of a derived class in a derived class object is rendered undefined, so the C + + compiler treats it as nothing, that is, when it enters a destructor of a base class, it treats the derived class object as a base class object, at which point any virtual function, typeID and dynamic_cast see it that way, too.

C + + primer that if you call a virtual function in a constructor or destructor, you are running a version that is defined by the constructor or destructor's own type . This sentence is ambiguous, but refers to the meaning of the above words. That is, when the base class part of a derived class object is constructed, the derived class object is treated as a base class object, and the virtual function version of the invocation is the version of the base class.

As can be seen from the above analysis, this is contrary to our expectations. So the only way to avoid this error is to make sure that neither your constructor nor the destructor calls a virtual function, and that all functions called by constructors and destructors do not call virtual functions.

The invocation order of the constructors is structured from the base class to the derived class. In the process of construction, the vptr is pointed to the vtable of this layer. And the behavior of virtual function depends on vptr. Therefore, in this layer constructor, the compiler cannot learn any information about the derived class, and therefore cannot form the correct vtable access.

As a summary of the above text, we end this article with a program:

#include <iostream> #include <typeinfo> #include <cstring> using Std::endl;

Using Std::cout; Class base{char *basename public:base (): basename (NULL) {basename = new Char[strlen (typeID (Base). Name ()) +1]
        ;
		strcpy (basename, typeID (Base). Name ());
	print ();//The call to this virtual function cannot invoke the virtual function of the subclass.
	~base () {print (); delete []basename;}

virtual void print () {cout << "0x" << this << "from Base," << basename << Endl;};
			   Class Derived:public base{char *derivedname public:derived (): Base (),//This line can be commented out, plus clearer.
		Derivedname (NULL) {derivedname = new Char[strlen (typeID (Derived). Name ()) +1];
		strcpy (Derivedname, typeID (Derived). Name ());
	Print ();
	~derived () {print (); delete []derivedname;} virtual void print () {cout << ' 0x ' << this << ' from Derived, ' << derivedname <<endl;}}
;
	int main () {cout << "now generate Base B:" << Endl;
	Base b; {cout << "\nnow generateDerived d: "<< Endl;

		Derived D;   cout<< "\ngenuine Virtual function call start!"
		<<endl;
		Base *pb=&b;
		Base *pd=&d;
		cout<<endl<< "Base Object, call virtual print ()" <<endl;
		Pb->print ();
		cout<<endl<< "Derived Object, call virtual print ()" <<endl;
		Pd->print ();   cout<< "Virtual function call end!"
		<<endl;   cout<< "\nnow Destruct the objects!"
	<<endl;   } cout<< "Derived D destruction done!"

	<<endl;
return 0;
 }

The running result of the program is:

Now generate base B:
0x0x22fef0 from base, 4Base now

generate Derived D:
0x0x22fee4 from base, 4Base
0x0x2 2fee4 from Derived, 7Derived

Genuine Virtual function call start!

Base Object, call virtual print ()
0x0x22fef0 from base, 4Base

Derived Object, call virtual print ()
0x0x22fee4 From Derived, 7Derived
Virtual function call end!

Now destruct the objects!
0x0x22fee4 from Derived, 7Derived
0x0x22fee4 from Base, 4Base
Derived d destruction done!
0X0X22FEF0 from Base, 4Base

As we can see, the derived d,this pointer is the same pointer for a derived class, but the virtual function version of the invocation is different.

Now generate Derived D:
0x0x22fee4 to Base, 4Base
0x0x22fee4 from Derived, 7Derived

This fully illustrates that the derived class object is treated as a base class object during the base class partial construction of the derived class object, and that any virtual functions, typeid, and dynamic_cast, and so on, are regarded as such.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.