[C++ classes and objects] What default member functions does a class have? (superior)

Table of contents

1. The 6 default member functions of the class

2. Constructor (*^▽^*)

2.1 Concept

2.2 Features

3. Destructor (*^▽^*)

3.1 Concept

3.2 Features

4. Copy constructor (*^▽^*)

4.1 Concept

4.2 Features

5. Assignment operator overloading (*^▽^*)

5.1 Operator overloading

5.2 Assignment operator overloading


ヾ(๑╹◡╹)ノ" People always have to pay for their past laziness!ヾ(๑╹◡╹)ノ"


1. The 6 default member functions of the class

If there are no members in a class, it is simply called an empty class.
There is not nothing in the empty class. When any class does not write anything, the compiler will automatically generate the following 6 default member functions.

 Default member function: The member function generated by the compiler without explicit implementation by the user is called the default member function.

2. Constructor (*^▽^*)

2.1 Concept

For the data class:

class Date
{
public:
	void Init(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1;
	d1.Init(2022, 7, 5);//初始化
	d1.Print();
	Date d2;
	d2.Init(2022, 7, 6);//初始化
	d2.Print();
	return 0;
}

For the above code, you can set the date for the object through the Init public method, and call this method to set the information every time the object is created.

The constructor is a special member function with the same name as the class name , which is automatically called by the compiler when creating a class type object to ensure that each data member has a suitable initial value, and is called only once in the entire life cycle of the object .

2.2 Features

The constructor is a special member function. It should be noted that although the name of the constructor is called construction, the main task of the constructor is not to open space to create objects, but to initialize objects .
feature:
1. The function name is the same as the class name.
2. No return value.
3. The compiler automatically calls the corresponding constructor when the object is instantiated .
4. The constructor can be overloaded. [However, most of what we write is the default constructor, and generally we don’t need function overloading [write a default constructor + other function overloading]]
class Date
{
public:
	// 1.无参构造函数
	Date()//构造函数:函数名与类名相同,无返回值
	{
		_year = 1;
		_month = 1;
		_day = 1;
	}
	// 2.带参构造函数
	Date(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _year;
	int _month;
	int _day;
};
void TestDate()
{
	Date d1; // 调用无参构造函数,注意,不能写成Date d1();
	Date d2(2015, 1, 1); // 调用带参的构造函数
	// 注意:如果通过无参构造函数创建对象时,对象后面不用跟括号,否则就成了函数声明
}
5. If there is no constructor explicitly defined in the class , the C++ compiler will automatically generate a default constructor without parameters . Once the user explicitly defines the compiler, it will no longer generate it . [That is, if the constructor is not implemented, the C++ compiler will automatically generate a default constructor with no parameters]

 Default constructor: (1) no-argument constructor (2) full default constructor (3) no-argument constructor generated by the C++ compiler [that is, there must be one of the three, if there is no default constructor] The written constructor is not without parameters, nor is it all default】It will report an error]

6. Regarding the default member function generated by the compiler, if the constructor is not implemented, the compiler will generate a default constructor. But it seems that the default constructor is useless? The object calls the default constructor generated by the compiler, but the object _year/_month/_day is still a random value [the built-in type is still a random value] . In other words , the default constructor generated by the compiler is useless here ?
Answer: C++ divides types into built-in types ( basic types ) and custom types. The built-in type is the data type provided by the language, such as: int/char..., and the custom type is the type we define ourselves using class/struct/union . When no constructor is implemented, the compiler generates a default constructor that calls its default member function on members of the custom type .

If the members of a class are all custom types, we can use the default generated functions. If there are built-in type function members, or if you need to display parameter initialization, you must implement the constructor yourself. (you need to pass parameters to initialize, you need to implement the constructor yourself) [most of them write constructors by themselves]

The default constructor generated by the C++ compiler does not handle the built-in type function member variables , and the custom type member will call its own default constructor.

Note: In C++11, a patch has been patched for the defect that built-in type members are not initialized, that is, built-in type member variables can be given default values ​​when declared in a class . [Note: This is a declaration, so it is a default value, not an initialization]
7. Both the parameterless constructor and the default constructor are called default constructors, and there can only be one default constructor.
Note: No-argument constructors, full default constructors, and constructors that we did not write to be generated by the compiler by default can all be considered default constructors.
class Date
{
public:
	Date()//无参的构造函数
	{
		_year = 1900;
		_month = 1;
		_day = 1;
	}
	Date(int year = 1900, int month = 1, int day = 1)//全缺省的构造函数
	{
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _year;
	int _month;
	int _day;
};

void Test()
{
	Date d1;//这里会发生错误,默认构造函数只能有一个
}

Errors occur at runtime, and conflicts occur.

In general, a C++ class must write its own constructor. There are only rare cases where you can let the compiler generate automatically:

(1) The members in the class are all self-defined type members, and these members provide default constructors.

(2) The default value is given when the built-in type member is declared.

3. Destructor (*^▽^*)

3.1 Concept

Destructor : Contrary to the function of the constructor, the destructor does not complete the destruction of the object , and the local object destruction is done by the compiler. When the object is destroyed, it will automatically call the destructor to complete some resource cleaning work of the class. 【destory】

3.2 Features

Destructors are special member functions.
feature:
1. The destructor name is the character ~ before the class name .
2. No parameters and no return value.
3. A class has one and only one destructor. If it is not explicitly defined, the system will automatically generate a default destructor [variables of custom types will call their own destructors, and variables of built-in types will not be processed]. Note: Destructors cannot be overloaded
4. When the object life cycle ends, the C++ compilation system automatically calls the destructor.
5.  Regarding the destructor automatically generated by the compiler, the default destructor generated by the compiler calls its own destructor for the custom type members.
6. If there is no resource application in the class, the destructor can not be written, and the default destructor generated by the compiler is used directly, such as the Date class; when there is a resource application, it must be written, otherwise it will cause resource leakage, such as the Stack class [In short, when there is a resource application, the destructor must be written].

4. Copy constructor (*^▽^*)

4.1 Concept

 When an object is created, a new object is created that is exactly the same as an object.

Copy constructor : There is only a single formal parameter , which is a reference to the object of this class type ( usually const decoration is commonly used ) , and is automatically called by the compiler when creating a new object with an existing class type object .

4.2 Features

1. The copy constructor is an overloaded form of the constructor .

2. The copy constructor has only one parameter and must be passed by reference , and the method of passing by value will cause infinite recursive calls .
class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	Date(const Date& d)//拷贝构造函数
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1;
	Date d2(d1);
	return 0;
}

Value-passing method: Calling the copy constructor will call the copy constructor. To call this function, you need to pass parameters first. Passing parameters is a temporary copy . At this time, the state is a temporary copy object, which is equivalent to copy construction, and you need to call copy construction function, an infinite recursive call will be triggered at this time.

Passing parameters by reference : the copy construction will not be called.

[An object initializes another object of this class, which is copy construction] [Copying an object is copy construction]

For custom type objects, the copy initialization should be completed by calling the copy constructor.

If no definition is displayed, the system generates a default copy constructor. The default copy constructor object is copied in byte order according to memory storage. This kind of copy is called shallow copy, or value copy. [That is, the members of the built-in type will complete the value copy (shallow copy), and the members of the custom type will call the copy construction of this member]
Conclusion: For general classes, the self-generated copy structure is enough, and there is no need to write the copy structure yourself. But for classes like stack, which manage resources directly by themselves, they need to implement deep copy by themselves.
4.  Then the default copy constructor generated by the compiler can already complete the value copy of byte order , do we still need to implement it ourselves? Of course classes like the Date class are unnecessary. Classes like stacks are not allowed. [There is an address in the stack, then the two stacks will go to the same space, and they will affect each other when adding, deleting, checking and modifying. When destroying, the same space will be destroyed twice, and the same space will be released twice. The program It will collapse—the ending solution, realize the copy construction by yourself-deep copy]
If there is no resource application involved in the class, the copy constructor can be written or not; once the resource application is involved, the copy constructor must be written, otherwise it is a shallow copy.

 In order to improve the efficiency of the program, when passing parameters to general objects, try to use the reference type as much as possible, and use references as much as possible according to the actual scene when returning.

5. Assignment operator overloading (*^▽^*)

5.1 Operator overloading

C++ introduces operator overloading to enhance the readability of the code . Operator overloading is a function with a special function name , and also has its return value type, function name, and parameter list. The return value type and parameter list are similar to ordinary functions.
The function name is : the keyword operator followed by the operator symbol that needs to be overloaded .
Function prototype : return value type  operator operator ( parameter list )
Return value: the result of the operation
Parameters: operation operands
Notice:
(1) New operators cannot be created by connecting other symbols: such as operator@
(2) The overloaded operator must have a class type parameter
(3) The meaning of the operator used for built-in types cannot be changed, for example: the built-in integer + cannot change its meaning
(4) When overloaded as a class member function, its formal parameters seem to be 1 less than the number of operands , because the first parameter of the member function is the hidden this
(5) .*     :: sizeof ?: . Note that the above 5 operators cannot be overloaded. This often comes up in written exams.             
//日期的判断是否相等
bool operator==(const Date& d1, const Date& d2)
{
	return d1._year == d2._year 
		&& d1._month == d2._month 
		&& d1._day == d2._day;
 }
//放到类里面 Date,此时是在类外面的写法
//1.
if (operator==(d1, d2))
{
	cout << "==" << endl;
}
//2/
if (d1 == d2)
{
	cout << "==" << endl;
}
//1.和2.是等价的,编译器会处理成1.

(1) Built-in types can directly use various operators, but custom types cannot directly use various algorithms. In order to allow various operators to be used by custom types, there is operator overloading.

(2) There are as many function parameters as there are operands. (== two operands; ++ one operand;)

Written in the class :

//日期的判断是否相等
bool operator==(const Date& d)
{
	return _year == d._year
		&& _month == d._month
		&& _day == d._day;
}
//放到类里面 Date,此时是在类里面的写法
//1.
if (d1.operator==(d2))
{
	cout << "==" << endl;
}
//2/
if (d1 == d2)
{
	cout << "==" << endl;
}
//1.和2.是等价的,编译器会处理成对应重载运算法调用

If both codes exist (the compiler can pass because it conforms to function overloading), the compiler will use the operator overloading in the class first.

//判断日期小
bool operator<(const Date& d)
{
	//小的情况
	if (_year < d._year
		|| (_year == d._year && _month < d._month)
		|| (_year == d._year && _month == d._month && _day < d._day))
	{
		return true;
	}
	else
	{
		return false;
	}
}

Attention to detail here, not to be taken for granted.

5.2 Assignment operator overloading

1. Parameter type
2. return value
3. Check whether you assign a value to yourself
4. return *this
5. If a class does not explicitly define an assignment operator overload, the compiler will also generate one to complete the byte-ordered value copy of the object
1. Assignment operator overload format
Parameter type : const T& , passing by reference can improve the efficiency of parameter passing
Return value type : T& , return reference can improve the efficiency of return, and the purpose of return value is to support continuous assignment
Check if you assign a value to yourself
Return *this : to compound the meaning of continuous assignment
//d2 = d1;-> d2.operator(&d2, d1)
Date& operator=(const Date& d)
{
	if (this != &d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
	return *this;
}
int main()
{

	Date d1(2000, 8, 20);
	Date d2(2000, 9, 17);
	Date d3(d1);//拷贝构造,一个存在的对象去初始化另一个要创建的对象
	d2 = d1;//赋值重载(复制拷贝) 两个已经存在的对象之间赋值
}
2. The assignment operator can only be overloaded as a member function of a class and cannot be overloaded as a global function
The assignment operator is overloaded into a global function. Note that there is no this pointer when overloading into a global function. Two parameters are required, but
If the assignment operator is not explicitly implemented, the compiler will generate a default one. At this time, the user implements a global
Assignment operator overloading conflicts with the default assignment operator overloading generated by the compiler in the class, so assignment operator overloading can only be a member function of the class .
3. When the user does not explicitly implement, the compiler will generate a default assignment operator overload, which is copied byte by byte in the form of value . Note: Built-in type member variables are directly assigned, while custom type member variables need to call the assignment operator overload of the corresponding class to complete the assignment.
4. The default assignment overload function generated by the compiler can already copy the value of byte order , do we still need to implement it ourselves? Of course classes like the Date class are unnecessary. If resource management is not involved in the class, it doesn't matter whether the assignment operator is implemented; once resource management is involved, it must be implemented.

Supplementary knowledge: Does the null pointer not exist? exists, and an empty address is an existing address.

Guess you like

Origin blog.csdn.net/m0_57388581/article/details/132179408