[C++] Talking about the constructor

What is a constructor?

The constructor is a function that is automatically called as the object is created, and its main function is to initialize the object.

C++ stipulates that the member function with the same name as the class is the constructor. The constructor should be a public member function, and the constructor has no return value type.

Constructors can be overloaded just like normal functions.

In C++, every class has and must have a constructor. If the user does not write a constructor by himself, the compiler will provide a constructor without parameters, called the default constructor.

But this default constructor does not do any initialization work. Once the user writes a constructor, the default constructor with no parameters disappears. If the user wants to have a parameterless constructor, he must write it himself.

The following is an example of overloading the constructor:

<span style="font-family:Microsoft YaHei;">#include <iostream>
using namespace std;

class Node
{
public:
	Node();
	//constructors with arguements
	Node(int i, char c = '0');
	Node(int i, char c, Node *p, Node *n);

	int readi() const;
	char readc() const;
	Node * readp() const;
	Node * readn() const;

	bool set(int i);
	bool set(char c);
	bool setp(Node *p);
	bool setn(Node *n);

private:
	int idata;
	char cdata;
	Node *prior;
	Node *next;
};

Node::Node()
{
	cout << "Node constructor is running..."<<endl;
	idata = 0;
	cdata = '0';
	prior = NULL;
	next = NULL;
}

Node::Node(int i, char c)
{
	cout << "Node constructor is running..."<<endl;
	idata = i;
	cdata = c;
	prior = NULL;
	next = NULL;
}

Node::Node(int i, char c, Node *p, Node *n)
{
	cout << "Node constructor is running..."<<endl;
	idata = i;
	cdata = c;
	prior = NULL;
	next = NULL;
}

int Node::readi() const
{
	return idata;
}

char Node::readc() const
{
	return cdata;
}

Node * Node::readp() const
{
	return prior;
}

Node * Node::readn() const
{
	return next;
}

bool Node::set(int i)
{
	idata = i;
	return true;
}

bool Node::set(char c)
{
	cdata = c;
	return true;
}

bool Node::setp(Node *p)
{
	prior = p;
	return true;
}

bool Node::setn(Node *n)
{
	next = n;
	return true;
}
</span>

<span style="font-family:Microsoft YaHei;">#include <iostream>
#include "node.h"
using namespace std;

int main()
{
	Node a; //create an object of Node, call the constructor
	Node b(8);
	Node c(8, 'F', NULL, NULL);
	cout <<a.readi()<<' '<<a.readc() <<endl;
	cout <<b.readi()<<' '<<b.readc() <<endl;
	cout <<c.readi()<<' '<<c.readc() <<endl;
	return 0;
}</span>

result:

Node constructor is running...
Node constructor is running...
Node constructor is running...
0 0
8 0
8 F

What is the constructor initialization list?

The constructor initialization list is a list of data members separated by a ":", followed by ",", each data is followed by an initialization expression in parentheses.

Explicit initialization when using the initialization list, and implicit initialization when the constructor of the initialization list is not used.


Execution of the constructor

The execution of the constructor can be divided into two phases, the initialization phase and the calculation phase. The initialization phase precedes the calculation phase.

All members of the class type will be initialized in the initialization phase, even if the member does not appear in the initialization list of the constructor.

/*
 * constructor2.cpp
 *
 *  Created on: 2016年2月20日
 *      Author: chenwei
 */
#include <iostream>
using namespace std;

class Test1
{
public:
	Test1():a(0) //constructor with no arguements
	{
		cout << "Constructor Test1" << endl;
	}
	Test1 (const Test1& t1) //copy constructor
	{
		cout << "Copy constructor for Test1" << endl;
		this->a = t1.a;
	}

	Test1& operator = (const Test1& t1)
	{
		cout << "assignment for Test1" <<endl;
		this->a = t1.a;
		return *this;
	}
private:
	int a;
};

class Test2
{
private:
	Test1 test1;
public:
	Test2(Test1 &t1)
	{
		test1 = t1;
	}
};

int main()
{
	Test1 t1;
	Test2 t2(t1);
	return 1;
}
<strong>
</strong>

result:

Constructor Test1
Constructor Test1
assignment for Test1


The first line corresponds to Test1 t1 in the main function, which constructs a Test1 object

The second line corresponds to the code in the constructor of the output Test2. The object test1 is initialized with the default constructor. The first two lines are the so-called initialization phase.

The third line corresponds to the assignment operator that outputs Test1, which is used to assign values ​​between two objects of the same kind, and copy test1. This is the so-called calculation phase.


What is the meaning of using the initialization list and assignment in the constructor body? What is the difference between the two?

For built-in data types and composite types (pointers, references), the performance and results of the two are the same.

For user-defined types (class types), the result is the same, but there is a big difference in performance. In the above example, if you use the initialization list instead, the printout will be different:

class Test2
{
private:
	Test1 test1;
public:
	Test2(Test1 &t1):test1(t1) {}
};
result:

Constructor Test1
Copy constructor for Test1

Using the initialization list reduces the process of calling the default constructor once, which is very efficient for data-intensive applications.


Member variable initialization order

1. When using the initialization list to initialize member variables, the order of initialization has nothing to do with the order in which they appear in the initialization list, only the order in which the member variables are declared.

Because the initialization order of member variables is based on the order of variables in memory, and the order of variables in memory is based on the order of declaration of variables.

<span style="font-family:Microsoft YaHei;">#include <iostream>
using namespace std;
class A
{
private:
	int n1;
	int n2;
public:
	A():n2(0), n1(n2+2) {}

	void Print()
	{
		cout << "n1:" << n1 << ", n2: " << n2 << endl;
	}
};

int main()
{
	A a;
	a.Print();
	return 1;
}
</span>

result:

n1: 4194434, n2: 0

Since n1 is defined before n2, n1 will be initialized first, but at this time n2 is not initialized, so the result of n1 will be a random value.


2. If the initialization list is not used, it is initialized in the constructor instead, and the initialization order is the same as the order declared in the constructor .

<span style="font-family:Microsoft YaHei;">	A()
	{
		n2 = 0;
		n1 = n2 +2;
	}</span>
result:

n1: 2, n2: 0


3. Class members cannot be initialized when they are declared.


4. The static member variables in the class must be initialized outside the class

The initialization sequence of static member variables is that the static member variables of the base class are initialized first, and then the static member variables of the derived class, knowing that all static member variables are initialized.

And because static variables and global variables are placed in the public memory area, the initialization of static variables and global variables is not in order, and static variables can be regarded as global variables with scope.

After all the initialization work is over, the main function will be called. If the constructor of a certain class is executed, the member variables of the base class will be initialized. Then there are the member variables of the derived class.

In short, it is static first, then common, base class first, then derived class.


What kind of member variables must be initialized through the initialization list?

1 const members, const members can not be initialized by assignment, only through the initialization list.

2 & Reference type, according to the definition of the reference, it must be initialized when it is defined, and cannot be reassigned, so it must also be initialized in the initialization list.

3 A member type is a class without a default constructor. If an explicit initialization list is not provided, the compiler will implicitly use the default constructor of the member type. If there is no default constructor, the compiler's attempt will fail. Through the initialization list, you can call the copy constructor instead of the default constructor to initialize.



Guess you like

Origin blog.csdn.net/michellechouu/article/details/50704224