We often say that when life is a class, if we do not specify a constructor for the class, then the compiler will implement a connstructor for us, then this is a certain right?
In fact, this is wrong. This is not what I said, is to understand the C + + object model in depth, the exact words are:
C + + Newbies generally have two common misconceptions:
- Any class that does not have the default constructor defined will be synthesized from one.
- The default constructor compiled by the compiler will explicitly set the defaults for each data member in the class.
first explain the 1th, only four cases will cause the compiler to synthesize a default constructor for classes that are not declared constructor. The synthesized constructor only satisfies the needs of the compiler (not the program). They are able to accomplish their task by "invoking the default constructor of member object or base class" or "initializing its virtual function mechanism or virtual base for each object" Class mechanism "to complete. As for the absence of those four cases, without declaring any constructor classes, we say that it has implicit trivial (shallow and incompetent, useless) that they are not actually synthesized.
These four synthetic constructor are discussed separately below:
Case one: A class contains a member object, and its member object has the default constructor
class Foo {public:foo (), foo (int) ...}; Class Bar {Public:foo Foo; char* str;}; Not inherited, is contains void Foo_bar () { bar bar; Bar::foo must be initialized here //: Bar::foo is a member object, and its class Foo has default constructor, which conforms to the subject of this subsection if (str) { }< c8/> ... }
When the class Bar contains a member object Foo, and Foo has the default constructor foo (), then the compiler will synthesize a default constructor for Bar, which looks like this:
Bar's default constructor may be synthesized //called by member Foo of Class Foo's default constructor inline Bar::bar () { / /c++ pseudo Code foo. Foo::foo (); }
Again, please note that the synthesized default constructor only satisfies the needs of the compiler, not the needs of the program, in order for this program fragment to execute correctly, the character pointer Str also needs to initialize, then the programmer may do this:
Bar::bar () {str = 0;} Programmer-Defined default constructor
At this point the compiler also needs to initialize the Member object Foo, but since the default constructor has been explicitly defined by the programmer, the compiler is not able to synthesize the second one. The action taken by the compiler is: "If Class A contains one or more member class object, then each constructor of Class A must call the default Construc for each member classes Tor, the compiler inserts the necessary default constructor into front of the user programmer's constructors. After inserting it may look like this:
Insert the default constructor //c++ pseudo code Bar::bar () { foo. Foo::foo (); inserted compiler code str = 0; //explicit user Code }
What if there are multiple class member objects that require an initialization operation? C + + invokes individual consructors according to the "member objects in class declaration order". This is done by the compiler. And if the default constructor of a member object is defined by the programmer, it will be called sequentially. Such as:
The programmer writes the default constructor to the Snow_white class, displaying the initialization of a member object snow_white::snow_white (): Sneezy (1024x768) { mumble = 2048 }
It will be expanded to:
Snow_white::snow_white (): Sneezy (1024x768) { //Insert Member Class Onject //Call its constructor dopey. Dopey::D opey (); Sneezy. Sneezy::sneezy (1024x768); Bashfun. Bashfun::bashful (); Explicit user code mumble = 2048; }
Case two: The base class with "default constructor" is similar, if a class without any constructors derives from a "base class with default constructor", Then the default constructor of the derived class will be nontrivial, and therefore need to be synthesized, which will invoke the default constructor of the previous base classes (according to their Order of declaration) 。 For a successor class, the synthesized constructor and a "explicitly provided default constructor" are no different. If the designer provides multiple constructors (such as constructor with an int parameter), but none of them have the default constructor? The compiler expands each of the existing constructors and inserts the base class's default constructor in front. If there are members member object, they are also called sequentially. Scenario three: Class with a "virtual Function"
If a class declares or inherits a virtual function and lacks a user-declared constructors, the compiler will detail the necessary information to synthesize a default constructor. Such as:
Class widget{public : virtual void Filp () = 0; ... } void Filp (const widget& Widget) {Widget.filp ();} Suppose both Bell and Whistle derive from the Widget void foo () { bell B; Whistle W; Filp (b); Filp (w); }
The following two expansion steps occur during compilation:
- A virtual function table (known as VTBL in Cfront) is generated by the compiler, with the virtual functions address of class.
- In each class Onject, an additional pointer member (that is, vptr) is synthesized by the compiler, containing the associated class VTBL address.
In addition, the WIDGET.FILP () virtual throw operation (invocation) is rewritten (in effect, the this change in the virtual function call) to use the FILP () entry in the widget's vptr and VTBL:
WIDGET.FILP () The transformation of the virtual trigger operation (invocation) //(* widget.vptr[1]) (&widget)
which
- 1 indicates the fixed index of FILP () in virtual table
- &widget represents the this pointer to "one of the called FILP () function entities"
To make this mechanism work, the compiler must set an initial value for each Widget (or its derived class) object's vptr, place the appropriate virtual table address, and for each constructor defined by class, The compiler inserts a pseudo-code similar to the previous article to do something like that. For classes that have nothing to declare, the compiler is like this topic, synthesizing a default constructor for them to initialize each class object's vptr correctly. (You can understand that Vptr must assign an initial value, like the pointer we normally use, without having to assign null). Scenario Four: The implementation of the Classvirtual base class with a "virtual base class" has a great difference between the different compilers. Then the common point of each implementation is that it must be the location of the virtual base class in each of its derived class object and be ready for the execution period. For example, in the following code:
Class X {public:int i;}; Class A:public virtual X {public:int J;}; Class B:public virtual X {public:double D;}; Class C:public A, Pulic B {public:int k;}; cannot be compiled to make it decision (resolve) out of pa->x::i position void foo (const * PA) {pa->i = 1024x768;} Main () { foo (new A); Foo (new C); // ... }
The compiler cannot fix the actual offset of "x::i accessed via Pa" in the Foo () function, because the true type of PA can be changed, and the compiler must change the code of "Execute access operation" so that the x::i can be deferred until the execution period is decided. This is usually done by placing a pointer in each virtual base classes of the derived class object "(equivalent to a middleware). All operations that "access a virtual base class via reference or pointer" can be done through the relevant pointers. In my case, foo () can be rewritten as follows to conform to this implementation strategy:
Possible compiler transitions, with a layer of void foo (const * PA) {pa->__vbcx->i = 1024;}
Where __VBCX represents the compiler-generated pointer to virtual base class X. The __VBCX is done during the class construction. For each constructor defined by class, the compiler will have a code that "allows execution of each virtual base class to be accessed". If class does not declare any constructors, the compiler must synthesize a default constructor for it. (Finally, my understanding is that, like this polymorphic pointer cannot be fixed, we need to give it a direction, not to let it be a random point, so the compiler will synthesize the default constructor). Well, the previous explanation is that the only four compilers can synthesize a default constructor for classes that do not declare constructor. Now explain this sentence:
- The default constructor compiled by the compiler will explicitly set the defaults for each data member in the class.
In the synthesized default constructor, only the base class Subobject and member objects are initialized. All other nonstatic data member, such as integers, integer pointers, integer arrays, and so on, are not initialized, and these initialization operations may be necessary for the program, but not necessarily for the compiler. If a program needs to "set a pointer to 0" of the default constructor, then the person who provides it should be a programmer.
When the C + + 2.1 compiler creates a default constructor