Effective c++--clause 7 (chapter 2nd)

Source: Internet
Author: User

Article 07: Declaring a virtual destructor for a polymorphic base class Declare destructors Virtual in polymorphic base classes

Design the following time base class Timekeeper:
Class Timekeeper {public:    timekeeper ();    ~timekeeper ();}; Class Atomicclock:public timekeeper {...}; Class Waterclock:public timekeeper {...}; Class Wristwatch:public timekeeper {...};
Many customers just want to use the time in the program, do not want to worry about the time how to calculate the details, it is possible to design the factory (factory) function, the return pointer to a timed object.The factory function "returns a base class pointer pointing to the newly generated derived class object":
Timekeeper *gettimekeeper ();    Returns a pointer to a dynamically allocated object of the Timekeeper derived class
To comply with the rules of the factory function, the object returned by Gettimekeeper () must be in the heap. Therefore, in order to avoid leaking memory and other resources, it is important to delete each object returned by the factory function appropriately:
Timekeeper *PTK = Gettimekeeper ();     Derive a dynamically allocated object from the Timekeeper inheritance system ...                                    Use it to delete ptk;                            Release it to avoid resource leaks
One of the weaknesses of the above code is that even if the client is doing everything right, there is still no way to know how the program will act.
The problem is that the pointer returned by gettimekeeper points to a derived class object (such as Automicclock), and that object is deleted via a base class pointer (such as a timekeeper* pointer), and the current base Class (Timekeeper) has a non-virtual destructor.
The cause of the disaster is that C + + explicitly states that when the derived class object is deleted by a base class pointer, and the base class carries a non-virtual destructor, the result is undefined-- The actual execution usually occurs when the derived component of the object is not destroyed.If Gettimekeeper returns a pointer to a Atomicclock object, its Atomicclock component is probably not destroyed, and Atomicclock's destructor is not executed. However, the base class component is usually destroyed, The result is a "partial destroy" object, which could form a resource leak and corrupt the data structure.
the solution to this problem is simple: give the base Class A virtual destructor, and then delete the derived class object to achieve the goal. It destroys the entire object, including all derived class components:
Class Timekeeper {public:    timekeeper ();    Virtual ~timekeeper ();}; Timekeeper *PTK = Gettimekeeper ();.. delete PTK;                                Now it's a good act
Base classes like timekeeper usually have other virtual functions in addition to destructors, because the purpose of the virtual function is to allow the implementation of the derived class to be customized. For example, timekeeper may have a Virtual GetCurrentTime, which has different implementation codes in different derived class. any class with the virtual function is almost certain that there should be a virtual destructor as well.
If class does not contain a virtual function, it usually means that it is not intended to be used as a base class. When class does not attempt to be treated as a base class, making its destructor virtual is often a bad idea.

Because the virtual function is implemented, the object must carry additional information, which is used primarily to determine which virtual function should be called at run time. This information is usually made up of a so-called vptr (virtual table pointer) The pointer points to a. Vptr points to an array of function pointers, called VTBL (virtual table), and each class with the virtual function has a corresponding VTBL. When an object calls a virtual function, The function that is actually called depends on the vptr of the object that the vtbl--compiler is referring to to find the appropriate function pointer.
The virtual function implementation details are unimportant and important If a class contains virtual functions, the volume of its objects increases. C + + objects are no longer structured like the same declarations in other languages, such as C, and therefore cannot be passed to functions written by other languages.
Therefore, it is wrong to declare all of the class's destructors as virtual in an unwarranted manner. It is common practice to declare a virtual destructor for a class only if it contains at least one virtual function.
Even if class is completely free of virtual functions, it is still possible to be injured by the "non-virtual destructor problem". For example, a standard string does not contain any virtual functions, but sometimes programmers mistakenly treat it as a base class:
Class Specialstring:public std::string {};
If you inadvertently convert a pointer-to-specialstring to a pointer-to-string at any point in the program, and then delete the string pointer that was obtained by the conversion, the previous disclosure problem occurs.
The same analysis applies to any class that does not have a virtual destructor, including all STL containers such as Vector,list,set and so on. Therefore, you should refuse to inherit a standard container or any other class with a non-virtual destructor.
Sometimes it may be convenient to have class with a pure virtual destructor. The pure virtual function results in abstract abstraction class--that cannot be manifested (instantiated) Class. That is, you cannot create an object for that type. But sometimes you want an abstract class, but there is no pure virtual function, what do you do? Because the abstract class is always used as a base class, and because the base class should have a virt UAL destructors, and because the pure virtual function leads to abstract class, the approach is simple: Declare a pure virtual destructor for the class that you want it to be abstract. For example:
Class Awov {public:    virtual ~awov () = 0;    DECLARE pure virtual destructor};
This class has a pure virtual function, so it is an abstract class, and because it has a virtual destructor, there is no need to worry about destructors. Here's a tip: You must provide a definition for this pure virtual destructor:
Definition of Awov::~awov () {}            //pure virtual destructor
The destructor works by the deepest derivation (most derived) whose destructor is called First, followed by the destructor of each of its base class. The compiler creates a pair in the destructor of the derived classes of the Awov: Awov, so you must provide a definition for this function.
Necessity of defining pure virtual destructor: The destructor of the derived class is called and then the destructor of each base class is called, and the pure virtual destructor of the abstract class is bound to be called. if a pure virtual destructor is simply declared and not defined, it can cause a runtime crash. The null implementation of the pure virtual destructor (as shown in the above line) guarantees the security of such code.
You can also use the pure virtual member function to locate the error code (see Defining a pure virtual destructor).
"Give base classes a virtual destructor", this rule applies only to polymorphic base classes. This base classes is designed to be used to "process derived through the base class interface." Class object ". Timekeeper is a polymorphic base class because you want to handle its different derived class objects.
Not all base classes are designed for polymorphic purposes. For example, standard string and STL containers are not designed to be used as base classes, not to mention polymorphism. Some classes are designed to be used as base classes, But not for polymorphic purposes, so they don't need a virtual destructor.
Note:
Polymorphic base classes should declare a virtual destructor. If class has any virtual functions, it should have a virtual destructor.
The purpose of classes is not to declare a virtual destructor if it is not used as a base classes, or is not intended for polymorphism.

Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

Effective c++--clause 7 (chapter 2nd)

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.