Constructor and destructor of C ++

Source: Internet
Author: User
Constructor provides a mechanism through which you can complete necessary initialization tasks to make objects meaningful.
Is not just an original space.

However, we gradually learn that constructor is not only applicable to users (ProgramFor the compiler.
Responsibilities are also extremely important. Through this mechanism, it makes some basic features of C ++ correct, such as inheritance and polymorphism.
Implementation and performance.

First of all, it is hard to understand that in constructors, we need to ensure the correct construction of the base class object, if it is inherited from the base class
. Because the inherited class object can be viewed as a base class object at least "low" and has all the actions and manifestations of the latter,
Therefore, the base class constructor is called first. If the so-called base class is inherited from other classes, this forms
A call chain. The final case is that the constructors of the most basic classes are first executed, and then the constructors of the previous layer.
Function, so as to inherit the class from the outermost layer. This process must be strictly ordered. Without this order guarantee, follow
Classes have the opportunity to access the data or functions of the base classes before the base classes are built. This will lead to unpredictable
And catastrophic consequences.

Only by ensuring the correct construction of the base class can we construct the inherited class itself. Because the class may contain
Member object, which must be constructed in a certain order (generally the order of variable Declaration ). Yes
Parameters are required for the construction of one or more member objects. All required parameters must be provided in the class constructor.
Number (constitute an explicit "initialization list ").

It seems that this is all implicit (or semi-implicit) Work of the constructor? No. We ignored an extremely important
Class association information (table ). Class association information is generated during compilation and is required for the class during runtime.
Additional data (the data can be considered in the global data zone ). We are familiar with the virtual function table (V-table), I
Put it in the category of class association information (initially, I thought the virtual function table was all, but this understanding is a bit narrow
). It also contains the runtime type information (rtti ). In addition, we do not exclude other auxiliary data that we do not know.
(In short, class association information is a broad and unified name ). If the compiler generates class association information for the class,
There is no doubt that it must be associated with the current object (instance of the class) in the constructor (maybe simply
You need to set a pointer ).

For example, if the class contains a virtual function, or it overwrites the virtual function in the base class (both of which mean that the class has
Your own virtual function table ). After the correct association is set, a pointer (V-PTR) will exist, which points
The virtual function table (V-table ). After that, polymorphism can show the expected correct behavior.

Again (importance of order), set association, or in a narrow sense, setting V-PTR must occur in the construction of the base class
After the function is called. Because if the inheritance class has its own virtual function table, the V-PTR will be rewritten to point to the table.
, Even if the previous V-PTR has been set by the base class. This is legal and expected. But in terms of semantics, we will never
Allow the base class to override the V-PTR set by the inheritance class. If the V-PTR setting occurs before the base class construction call
This illegal scene will happen.

After all the above tasks are completed (for users, they are almost implicit), they can truly start to execute the user's initial
InitialCode.

What happens when a virtual function is called in the constructor? The cause may be unexpected. The object of the current class is
During construction, V-PTR points to the virtual function table of the current class. At this time, the inherited class has not executed its own code (such
When V-PTR is set and initialization code is executed, all occurs after the constructor of the current class is executed. So
The virtual function version of the class is to be executed, rather than the version of the inherited class that may be overwritten. Here is a negative
. If the V-PTR setting occurs before the base class constructor is called, we have the opportunity to call the virtual function of the inherited class.
Version. What does this mean? The inherited class has not been initialized yet (so the object has not been built), And we attempt
The consequence of executing a member function on an unconstructed object is disastrous.

When is the class constructor called? When an object is created. The object may be located in the stack, global data zone, or heap.
. The object may be created in the declared place. Such an object is located in the stack or global data zone. Objects can also be used
The new operator is dynamically created, so that the object will be on the stack.

Destructor
The Destructor provides a mechanism opposite to the constructor that allows you
Space used by the OSS. Again, what we care about here is what happens at the underlying language level.
Events.

The execution order of the constructor is the opposite. The Destructor starts to execute from the outermost class and the destructor of the most basic class.
The number of final executions looks like a layer-by-layer shelling. The reason for this order to be strictly guaranteed is also obvious (against
Reverse Order will also cause relevance issues ). The result looks like this: User destructor code-> member object destructor-> Base
Class destructor.

The Destructor is called when the object row is destroyed. When an object exceeds its scope, such as a local variable inside a function
Will be destroyed automatically when the function returns. For objects created on the stack, we can only execute D through the Object Pointer p.
Elete P to destroy it. Now there is a problem. P points to an object of a certain type (such as a), but it may be
Through upcast, it actually points to a B object, so what will happen?

Obviously, the correct method is to destroy the object as B's instance. That is to say, call the destructor of B. We may
I think of it very quickly. First, I can know the type of the object "actually" at runtime (the latest Derivation
Class, which is assumed to be B in this example), for example, through rtti. Then, locate and call
Destructor. However, this idea is not implemented naturally. You need to compile the class type information and
Function pointers are associated. However, the above considerations seem complicated. We can put this destructor pointer
Virtual function table (a special position ). The reason is that it is very similar to a virtual function.
The slot can be overwritten by the inherited class (which points to the destructor of the inherited class), and the inherited class should always overwrite it (
However, we can see that the actual situation is different from "always overwrite ).

In any case, the destructor pointer is stored in the class association information (table) mentioned above, which is not difficult for the compiler to find. Because
When a delete operation is performed through an object pointer (even if it has been traced), the correct destructor can always be called.
. However, in the experiment of multiple compilers, it is found that the inheritance class will only overwrite the destructor of the base class as virtual.
It. It seems that the virtual function technology is used to treat the destructor. If the destructor of the base class are not declared as virtual
When the previous Delete P is executed, only the destructor of A is executed, while that of B is not!

This is surprising. Allow "incomplete" structure, and assign the right and responsibility to the programmer.
! I'm not sure what the main reason is. Maybe it is because C ++ places so much emphasis on efficiency that it forces programmers
When necessary, explicitly declare his needs, because indirect calls like virtual functions occupy additional space and time.

We have discussed the behavior of virtual functions in constructor. Let's continue to look at the situation in destructor. Because the structure has been
The process is self-exclusive. When the current class calls the virtual function, its inheritance class has previously completed the structure analysis, and is no longer feasible.
. Therefore, the virtual function version of the inherited class cannot be called. As a result, the local version (
Similar to the conclusions in function creation, the virtual function mechanism is ignored ).

Refer to <thingking in C ++>, Bruce Eckel!

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.