[Effective C ++ series]-declares Virtual destructor for the polymorphism base class, and implements tivevirtual
Declare destructors virtual in polymorphic base classes.
C ++ points out that when a derived class object is deleted by a pointer of the base class type, if the base class has a non-virtual destructor, the result of the structure will be undefined. That is, the base class component of the object is usually destructed, but its derived class component is not destroyed, and even the derived class destructor are not called. Therefore, an object that is "partially destroyed" is formed, causing resource leakage.
For example:
class car{public: car(); ~car(); ... }; class diesel_car : public car {…};class solar_car: public car {…};class electric_car : public car {…};When a customer uses a car object in the Code, if he doesn't care about the specific type of car, we can design a factory function (or factory class) to create a car object, the factory function returns a base class pointer or reference pointing to the newly generated derived class object:
car* get_car();
To comply with the factory function rules, the returned object must be in the heap (otherwise, the pointer returned by the function will point to an invalid position after the function returns, because the lifecycle of the stack object is a function field), in order to avoid Memory leakage, the customer code needs to delete the objects returned by the factory function properly:
Car * p_car = get_car (); // obtain a dynamic allocation object from the car inheritance system... // Use this object delete p_car; // release this object to avoid Memory leakage
First, we need to note that the above practices already have two defects:
1. Depending on the customer code to execute the delete operation, there is an error tendency, and the customer may forget to do this. 2. The factory function structure should consider preventing common Customer Code errors. However, the most fundamental weakness is that the customer Code cannot completely destroy the returned derived class object. A simple practice is to define a virtual destructor for the base class. After deleting the derived class object, the object will be destroyed, including all the derived class components.
class car{public: car(); virtual ~car(); ... };
When a class needs to be used as a Polymorphism, a virtual destructor should be declared for the class, that is to say, any class with a virtual function should also have a virtual destructor. However, if the class does not have a virtual function, that is, it is not used for Polymorphism purposes, it usually means that it is not intended to be used as a base class (except for some special cases, such as noncopyable class ). When a class is not used as a base class, it is best not to define a destructor for it. It is costly to define a function as virtual in C ++. This is the virtual table pointer of the virtual table pointer. To implement a virtual function, the object must carry certain information to determine which virtual function to call at runtime. This information is usually pointed out by a so-called vptr (virtual table pointer) pointer. Vptr points to an array composed of function pointers and becomes vtbl (virtual table). Each class with virtual functions has a vtbl. When a virtual function is called for an object, and the called function depends on the vtbl pointed to by the vptr of the object. The Compiler looks for an appropriate function pointer in it. Therefore, every class object that defines a virtual function contains a vptr. In this way, the object volume will increase because of the existence of virtual functions. For example:
class point{public: point(int coord_x, int coord_y); ~point();private: int x, y;};In a 32-bit system, the int type occupies 32 bits, so the point object occupies 64 bits and can be inserted into a 64bit cache, it can even be passed as a "64-bit volume" to functions written in other languages such as C living FORTRAN. However, if the point contains the destructor, the space occupied by the point object will be 96 bits (two ints plus one vptr ). The object volume increases from 64bits to 96 bits. In the 64-bit computer architecture, the point object occupies 128 bits (because the pointer type occupies 64 bits ). The object volume increases from 64bits to 128 bits. Such an object cannot be inserted into a 64-bit cache, and the point object of C ++ no longer has the same structure as the same declaration in other languages (such as C, therefore, it cannot be passed to functions written in other languages, so there is no portability. Therefore, it is unreasonable to declare the destructor of a class that is not used for Polymorphism as virtual. The Destructor should be declared as virtual only when the class contains at least one virtual function.
Do not try to inherit any classes with non-virtual destructor, including all STL containers such as vector, list, set, unordered_map, and string. This will cause resource leakage! Unfortunately, C ++ does not provide a "prohibit derived" mechanism similar to java's final classes or sealed classes in c.
When you want to define a class as an abstract class (pure virtual class), but are there any pure virtual functions, it is very convenient to declare a pure virtual destructor for this class.
class abstract_class{public: virtual ~abstract_class() = 0;};Note: You must provide a definition for this pure virtual destructor:
abstract_class::~abstract_class(){}Because the operating method of the Destructor is: The destructor of the class of the deepest derivative (most derived) is called first, and then the destructor of each base class is called. The compiler will create a pair in the derived classes of abstract_class ~ The call Action of abstract_class, so it must be ~ Define act_class. Otherwise, the linker reports an error.
1. polymorphic (with polymorphism) base classes should declare a virtual destructor. If the class has any virtual function, a virtual destructor should be declared for it. This base class is designed to "process the derived class object through the base class interface ". 2. Some classes are not designed to be used as base classes, or even as base classes do not have polymorphism. Such classes should not be declared as virtual destructor.
The default destructor is public and non-virtual.