Default member function: Explain the implicit operation of the class in detail

insert image description here

1. The default member function of the class

The default member function of a class is a member function that is automatically generated after a class is defined. If we display the definition, the class will not be automatically generated.

2. Constructor

In the stage of data structure learning, we tore through data structures such as stacks, linked lists, and queues. At that time, we implemented them in C language. Each data structure has its own initialization and destruction functions. These two functions are very important to the use of data structures, but we often forget to use them, so C++ sets a default member function in the class - the constructor , which functions as an initialization function .
He has the following characteristics:

  1. The function name is the same as the class name.
  2. No return value (even void does not need to be written )
  3. function can be overloaded
  4. If there is no explicit definition, it will be called automatically when the class member is instantiated

There are also the following features to note, here we use the classic date class for explanation:

class Date
{
    
    
public:
	Date()//无参的构造函数
	{
    
    
		_year = 2023;
		_month = 5;
		_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; 
};

In the above code, we have already defined the constructor clearly—one with no parameters and one with all defaults . Obviously, there will be differences when we want to call it, so we stipulate that when calling a function without parameters, we don’t even need to write parentheses :

int mian()
{
    
    
	Date d3(2023,4,5);//调用全缺省的构造函数
	return 0;
}

If no constructor is explicitly defined in the class, the compiler will generate a default constructor with no parameters. But the automatically generated default constructor will only initialize the custom type and not the built-in type ( different on different compilers ). The built-in type is the data type provided by the language, such as: int/char, etc., and the custom type is the type defined by ourselves, such as: struct/class/union, etc.
This problem arises, if we forget to define the constructor in the date class, because the members of the date class are all built-in types, the constructor automatically generated by the compiler cannot complete the initialization of the class members , so it is stipulated in C++11 , the built-in type member variable can be given a default value when it is declared in the class . There are also things to note: no-argument constructors, full default constructors, and constructors that we didn’t write to be generated by the compiler by default can all be considered default constructors.
So when do we need to write the constructor ourselves, and when do we use the compiler to generate it:

  1. Generally speaking, when there is a built-in type and the built-in type does not have a default value that meets the requirements, we need to write our own constructor .
  2. If the members are all custom types, you can use the default member functions generated by the compiler

3. Destructor.

The destructor is the destruction and cleanup function to complete the cleanup of object resources. It has the following characteristics:

  1. The destructor name is the class name preceded by ~.
  2. Destructor has no return value and no parameters
  3. The destructor cannot be overloaded. A class can only have one destructor. If it is not explicitly defined, the compiler will automatically generate it.
  4. When the object life cycle ends, the system automatically calls the destructor.

Destructors are similar to constructors: built-in types do nothing, and custom types call their destructors.
Judging from this:

  1. In general, if there is a dynamic application for resources , it is necessary to explicitly write the destructor to release the resources
  2. There are no dynamically applied resources, no need to write destructors
  3. Members that need to release resources are all custom types , and do not need to write destructors

4. Copy constructor

When we want to create two objects with the same members, we can initialize them with existing objects , which requires the use of the copy constructor. It has only one formal parameter that is a reference to the object of this type . The copy constructor is an overload of the constructor . If the formal parameter does not use a reference but is called by value, it will cause infinite recursive calls—because the built-in type calls by value. The intermediate variable copy is completed, while the value copy of the custom type parameter needs to be completed by the copy constructor .
If not explicitly defined, the compiler will automatically generate a default copy constructor: the built-in type will complete the value copy/shallow copy , and the custom type will call his copy constructor. Note: If the resource application is not 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 .

Pointers are built-in types no matter what type they are.

Five. Assignment operator overloading

Operator overloading is a function with a special function name.
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)
operator overloading needs to pay attention to the following points:

  1. An overloaded operator must have a class type parameter
  2. Operators used for built-in types, whose meaning cannot be changed, for example: built-in integer +, whose meaning cannot be changed
  3. New operators cannot be created by concatenating other symbols: e.g. operator@
  4. When overloaded as a class member function, its formal parameters appear 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.

Code such as the following is operator overloading:

// >运算符重载

	bool operator>(const Date& d)
	{
    
    
		return !(*this <= d);
	}




	// ==运算符重载
	bool operator==(const Date& d)
	{
    
    
		return _year == d._year
			&& _month == d._month
			&& _day == d._day;
	}



	// >=运算符重载
	bool operator >= (const Date& d)
	{
    
    
		return !(*this < d);
	}


	// <运算符重载
	bool operator < (const Date& d)
	{
    
    
		if (_year < d._year)
		{
    
    
			return true;
		}
		else if (_year == d._year && _month < d._month)
		{
    
    
			return true;
		}
		else if (_year == d._year && _month == d._month && _day < d._day)
		{
    
    
			return true;
		}
		else
		{
    
    
			return false;
		}
	}


	// <=运算符重载
	bool operator <= (const Date& d)
	{
    
    
		return !(*this > d);
	}


	// !=运算符重载
	bool operator != (const Date& d)
	{
    
    
		return !(*this == d);
	}

Pay attention to assignment operator overloading:

  1. Parameter type: const T&, passing by reference can improve the efficiency of parameter passing
  2. Return value type: T&, return reference can improve the efficiency of return, and the purpose of return value is to support continuous assignment
  3. Check if you assign a value to yourself
  4. Return *this: to compound the meaning of continuous assignment
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;
 }
 
 Date& operator=(const Date& d)
 {
    
    
 	if(this != &d)
 	{
    
    
 		_year = d._year;
 		_month = d._month;
 		_day = d._day;
 	}
 	return *this;
 }

private:
 int _year ;
 int _month ;
 int _day ;
};

There are a few more points to note!
Assignment overloading cannot be written as a global function (the default member function cannot be written as a global function), but the declaration and definition can be separated (and it is not necessary to pay attention to the problem of private access to class members) C++ regulations: ++
a prefix operator a.operator() No need to add parameters a++ postfix operator a.operator(int) need to add parameters.
When a unary operator is overloaded as a member function, there are no parameters in the parameter list, and the only operand is hidden in the parameter list in the form of this pointer; when it is overloaded as a non-member function, the only operand must appear in the parameter list table.

Guess you like

Origin blog.csdn.net/qq_43289447/article/details/130455314