Synthesis of C ++ default constructor

Source: Internet
Author: User
Tags constructor inheritance

Misunderstanding of default constructors

1. When the program ape defines the default constructor, the compiler will directly use this default constructor.

A simple example

Class Student;
Class School
{
Public:
School (){}
...
Student students;
};

We know that an object will call its constructor when it is defined. The default constructor above does not call the students constructor. Therefore, the compiler never directly uses our default constructor. For details, refer to the following section. Here, we will only ask questions.


2. When the programmer does not define the constructor, the compiler will help us define the default constructor.

Next, let's take these incorrect ideas into the text.


Why define the default constructor for us?

A simple example

Class Student
{
Public:
Student () {}// defined
Void Study (); // only the declaration is given, not defined
...
};
Void main ()
{
Student stu;
// Stu. Study (); // call an undefined function
}

The above is a complete code that can be compiled, connected, and run. Among them, the Study () function is only declared, but not defined, but compiled? Why? Because you didn't use it. Even if you cancel the annotation of the line of code, it will not encounter errors during the compilation period, and the compiler will only prompt errors when the connection is complete. For more information, see this blog. You can also ignore it. Remember this: when the compiler does not need a function (the above is because the Study function is not called in the code), this function can not be implemented. Therefore, you can declare many useless functions very irresponsibly in your code and do not implement any of them.

Back to our content, "Why help us define the default constructor", the answer is that the compiler is used, but you have not clearly defined it. Note: This is not required by the program, but by the compiler. The program needs to be used, that is, we want the members and base classes in the class to be properly initialized. The compiler requires that, without this function, the compilation connection cannot be normally performed.


Then the problem arises. When does the compiler have this need.


The compiler requires a default constructor under four requirements.


First requirement

If a class does not have any constructor, but it contains a member object, and the latter has a default constructor, the implicit default constructor of this class is "nontrivial ", the compiler needs to synthesize a default constructor for this class. However, this merging operation only happens when the constructor needs to be called.

Here we reference the words in the book. Nontrivial is useful. Here is an example.

Class Student
{
Public:
Student (){}
...
};
Class School
{
Student students; // It is not an inheritance, it is an inclusion
Char * name;
...
};
Void main ()
{
Int;
School school; // The merging operation occurs here
}

In the above example, the compiler synthesize a default constructor for the School class, because the Student contained in the School has the default constructor, while we construct the School, you need to call the default constructor of Student, so the compiler will help us synthesize a default constructor, which looks like the following.

School: School ()
{
Students. Student ();
}

Note: School: name initialization is a program requirement, not a compiler requirement. Therefore, the constructor does not initialize the name. The requirements of the compiler are not the same as those of the program.

Back to the above program, the compiler is merged in the second line of code in main. I still remember the previously mentioned functions that only declare undefined functions, even if we didn't instantiate School in the above code, this merging operation will never be performed, because the compiler does not need it !!! The compiler performs synthesis only when this default constructor is used.

There is another problem here. If we set the constructor ourselves, but didn't call the constructor of the internal object, will the compiler combine into a new constructor? No. The compiler only inserts the "required by the compiler" code in the existing constructor. A simple example.

Class Student
{
Public:
Student (){}
...
};
Class School
{
Public:
School () {name = NULL} // students not initialized
Student students; // It is not an inheritance, it is an inclusion
Student students2;
Char * name;
...
};
// The compiler inserts the required code. The final constructor is similar to the following:
School: School ()
{    
// Insert your own code to ensure that all objects are initialized before use.
Students. Student ();
Students2.Student (); // multiple objects are inserted in the declared order.
Name = NULL;
}

Second requirement

If a class without any constructor is derived from a base class with "default constructor", the default constructor of the derived class will be considered nontrivial and therefore need to be synthesized.

This is similar to the first requirement. Note the following.

1. In the constructor (existing or merged) of the derived class, the compiler inserts the base class constructor in addition to the constructor of the member class object.

2. The call time of base class constructor is before the member class object.


Third requirement

Class declares (or inherits) a virtual function. When the constructor declared by the programmer is absent, the compiler synthesize a default constructor.

We know that, in the process of calling a virtual function, the specific function is unknown in the compiler. For example

Class Base
{
Public:
Base ();
Virtual void Print ();
};
Class Derived: public Base
{
Public:
Derived ();
Virtual void Print ();
};
Void Print (Base * para)
{
Para-> Print ();
}
Void main ()
{
Base;
Derived B;
Print (a); // call Base: Print ();
Print (B); // call Derived: Print ();
}

How does the compiler know which Print () is called? When the class contains the virtual function, the compiler inserts the "virtual table pointer" in the class and initializes it in the constructor. The virtual table pointer points to the virtual function table, which records the addresses of each virtual function. The reason why the program can realize polymorphism is actually because the address in this table is dynamically used when the virtual function is called.

Back to the question, it should be emphasized that when there is a virtual function, the compiler needs to construct a virtual table pointer. Therefore, if we do not have any constructor, the compiler will combine them into a default constructor, which meets the preceding "first requirement and second requirement, the initialization of the virtual table pointer is also completed after the Base class is constructed. If the constructor has been defined, the virtual table pointer initialization will be completed after base class constructors and before member initialation list.


Fourth requirement

Class is derived from an inherited string. One or more virtual base classes exist. When no constructor is defined by the program ape, the compiler combines them into a default constructor. For example

Class X
{
Public:
Int I;
};
Class A: public virtual X {};
Class B: public virtual X {};
Class C: public A, public B {};
Void Foo (const A * pa)
{
Pa-> I = 1024;
}
Void main ()
{
Foo (new );
Foo (new C );
}

The compiler cannot accurately know the actual offset position of X: I accessed through pa, because the actual type of pa can be changed. The compiler must change the code that "executes the access operation" so that X: I can be delayed until the execution period is reached. For each constructor defined by the class, the compiler inserts the code that "allows each virtual base class" to perform access operations during the execution period. The compiler must synthesize a default constructor for how the class does not declare any constructor.



C ++ default constructor

Default constructor

The default constructor is a constructor that provides default values for all parameters. It usually refers to a constructor without parameters. For example, in the following class Test, its default constructor is Test ().

Class Test
{
Public:
Test () {}// default constructor
};

If you do not provide any constructors for your class, the compiler will automatically generate a default no-argument constructor for you. Once you define a constructor for your class, the compiler will not generate the default constructor.


Provide default constructor for your class

There are many reasons for this:

1. When you use an array statically allocated and the array element type is an object of a class, you need to call the default constructor, such as the following code.

Object buffer [10]; // call default constructor

2. when you use an array that is dynamically allocated and the array element type is an Object of a class, you need to call the default constructor. For example, the following code, if the Object does not have a default constructor, it cannot be compiled because the new operator calls the non-argument constructor class of the Object class to initialize each array element.

Object * buffer = new Object [10];

3. When you use a standard library container, if the element type in the container is an object of a class, the default constructor is required for this class, for the same reason as above.

Vector <Object> buffer;

4. when A class A is A member of another class B, if A provides A non-argument constructor, but B does not, A cannot use its own no-argument constructor. The following code will cause compilation errors.


Class B
{
B (int I ){}
};

Class
{
A (){}
B B;
};

Int main (void)
{
A a (); // error C2512: 'B': no appropriate default constructor available

Getchar ();
Return 0;
}



Similar to the following code, Class A defines the copy constructor without providing the default constructor. Class B inherits from Class, therefore, B needs to call the constructor of A to initialize A during initialization, and A does not have the default constructor. Therefore, A compilation error is generated.


Class
{
A (const &){}
};

Class B: public
{
    
};

Int main (void)
{
B B; // error C2512: 'B': no appropriate default constructor available

Getchar ();
Return 0;
}

Related Article

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.