Part 2 of Classes and Objects (Easy to Understand)


Preface

Does an empty class really have nothing? The answer is no, it will automatically generate 6 default member functions internally (the user does not show the implementation, the compiler generates them by default).
Insert image description here


1. Constructor:

1. Concept:

Let’s look at a piece of code first:

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, 8, 1);//初始化
	d1.Print();
	return 0;
}

We can see that Init needs to be called every time an object is created, and it is likely to be forgotten in daily use. Can it be automatically initialized when an object is created? The answer is yes, the constructor will be automatically called to initialize the object when the object is created.

2. Features:

The main task of the constructor is to initialize the object and is automatically called by the compiler when the object is created.
Features:

  1. The function name is the same as the class name.
  2. The compiler automatically calls the corresponding constructor when the object is instantiated.
  3. No return value.
  4. Can be overloaded.
class Date
{
    
    
public:
	// 1.无参构造函数
	Date()
	{
    
    }
	// 2.带参构造函数
	Date(int year, int month, int day)
	{
    
    
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
    
    
	Date d1;//调用无参构造
	Date d2(2022, 8, 1);//调用有参构造
	return 0;
}
  1. If the constructor is not explicitly defined in the class, the compiler will automatically generate one.
    Note: The default constructor automatically generated by the compiler does not handle built-in types (int, char...), and custom types will automatically call their constructors.
    As shown in the figure below: _n inside the class B instantiated object b1 is still a random value, and _a is a custom type that has been initialized.

Insert image description here
Then how to make the default generated constructor also initialize built-in types?
C++11 has patched the defect of not initializing built-in type members, that is: built-in type member variables can be given default values ​​when declared in a class.
How to use it:
Insert image description here

2. Destructor:

The destructor is the opposite of the constructor. It completes the cleanup of the object.
Note: The destructor does not complete the destruction of the object itself, the local object destruction is completed by the compiler. When the object is destroyed, the destructor will be automatically called to complete the cleanup of the resources in the object

Features:

  1. The name of the destructor is preceded by ~ before the class name.
  2. Automatically called when the object life cycle ends.
typedef int DataType;
class Stack
{
    
    
	Stack(int capacity = 3)//构造函数
	{
    
    
		_array = (DataType*)malloc(sizeof(DataType) * capacity);
		if (nullptr == _array)
		{
    
    
			perror("malloc申请空间失败!!!");
			return;
		}
		_capacity = capacity;
		_top = 0;
	}
	~Stack()//析构函数
	{
    
    
		if (_array)
		{
    
    
			free(_array);
			_array = nullptr;
			_capacity = 0;
			_top = 0;
		}
	}
private:
	DataType* _array;
	int _capacity;
	int _top;
};
  1. No parameters and return value.
  2. Even if the implementation is not shown, the compiler will automatically generate it.

Similar to the constructor, the destructor will automatically call its destructor for a custom type. For built-in type members, no resource cleanup is required during destruction. In the end, the system can directly reclaim its memory.

Note: If there is no resource application in the class, the destructor does not need to be written. For example, the Date class can directly use the default destructor generated by the compiler. When there is a resource application, such as the Stack class, it must be written, otherwise it will cause resource leakage.

3. Copy structure:

Copy constructor: There is only a single formal parameter. This formal parameter is a reference to an object of this class type (generally commonly used with const modification). It is automatically called by the compiler when creating a new object with an existing class type object.

Features:

  1. Copy construction is an overloaded form of constructor. Therefore, the function name is also the class name.
  2. The copy constructor parameter is called by reference. Failure to call by value will cause infinite recursion.
    Insert image description here
class Date
{
    
    
public:
	Date(int year = 2022, int month = 8, int day = 17)//构造函数
	{
    
    
		_year = year;
		_month = month;
		_day = day;
	}
	//Date(const Date date)//错误写法
	Date(const Date& date)//拷贝构造
	{
    
    
		_year = date._year;
		_month = date._month;
		_day = date._day;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
    
    
	Date d1(2022, 8, 1);//调用无参构造
	Date d2(d1);//拷贝构造1
	Date d2 = d1;//拷贝构造2
	return 0;
}
  1. If not explicitly defined, the compiler will generate a default copy constructor. The default copy constructor object copies the object in byte order according to memory storage. This type of copy is called shallow copy, or value copy.

Note: If there is no resource application involved in the class, the copy constructor can be written or not; once resource application is involved, the copy constructor must be written, otherwise it will be a shallow copy.

4. Assignment operator overloading:

1. Operator overloading:

C++ introduces operator overloading in order to enhance the readability of the code. Operator overloading is a function with a special function name, which also has its return value type, function name and parameter list. Its return value type and parameter list are similar to those of ordinary functions.
The function name is: The keyword operator is followed by the operator symbol that needs to be overloaded.
Function prototype: Return value type operator (parameter list)

Notice:

  1. Overloaded operators must have a class type parameter.
  2. Operators used for built-in types cannot change their meaning. For example, the built-in integer type + cannot change its meaning.
  3. New operators cannot be created by concatenating other symbols: such as 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 hidden this.
  5. .* :: sizeof ? : . Note that the above five operators cannot be overloaded. This often appears in multiple-choice questions in written exams.
class Date
{
    
    
public:
	Date(int year = 2022, int month = 8, int day = 17)//构造函数完成类的初始化
	{
    
    
		_year = year;
		_month = month;
		_day = day;
	}
	bool operator==(const Date date)
	{
    
    
		return _year == date._year
			&& _month == date._month
			&& _day == date._day;
	}
	bool operator!=(const Date date)
	{
    
    
		return !(*this == date);
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
    
    
	Date d1(2022, 8, 1);//调用无参构造
	Date d2(2022, 8, 2);
	d1 == d2;
	return 0;
}

2. Assignment operator overloading:

Format:

  1. A single formal parameter that is a reference to an object of this class.
  2. The return value type is a reference, which can improve the efficiency of return. The purpose of having a return value is to support continuous assignment.
  3. Check whether you assign a value to yourself.
  4. Return *this: to comply with the meaning of continuous assignment.
class Date
{
    
    
public:
	Date(int year = 2022, int month = 8, int day = 17)//构造函数完成类的初始化
	{
    
    
		_year = year;
		_month = month;
		_day = day;
	}
	bool operator==(const Date date)
	{
    
    
		return _year == date._year
			&& _month == date._month
			&& _day == date._day;
	}
	bool operator!=(const Date date)
	{
    
    
		return !(*this == date);
	}
	Date& operator=(const Date& date)
	{
    
    
		if (*this != date)
		{
    
    
			_year = date._year;
			_month = date._month;
			_day = date._day;
		}
		return *this;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
    
    
	Date d1(2022, 8, 1);//调用无参构造
	Date d2(2022, 8, 2);
	d1 == d2;
	return 0;
}

Features:

  1. When the user does not explicitly implement it, the compiler will generate a default assignment operator overload, copying byte by value in the form of value.
  2. The assignment operator can only be overloaded as a member function of the class and cannot be overloaded as a global function.

Note: The assignment operator is easily confused with the copy constructor

int main()
{
    
    
	Date d1(2022, 8, 1);//调用无参构造
	Date d2(d1);//拷贝构造写法1
	Date d2 = d1;//拷贝构造写法2
	d2 = d1;//赋值运算
	return 0;
}

5. const members:

The "member function" modified by const is called a const member function. Const actually modifies the this pointer implicit in the member function, indicating that no member of the class can be modified in the member function.
Insert image description here
Insert image description here

6. Overloading of address-taking and const address-taking operators:

These two default member functions generally do not need to be redefined, and the compiler will generate them by default.

class Date
{
    
    
public:
	Date* operator&()
	{
    
    
		return this;
	}
	const Date* operator&()const
	{
    
    
		return this;
	}
private:
	int _year; // 年
	int _month; // 月
	int _day; // 日
};

These two operators generally do not need to be overloaded. Just use the default address-taking overload generated by the compiler. Only in special circumstances, overloading is needed, such as if you want others to get the specified content!


Summarize

The above is the content of today’s part about classes and objects, including the six default member functions of classes. I hope it will be helpful to you who have just read this blog!

Guess you like

Origin blog.csdn.net/weixin_61661271/article/details/126512195