[C++ ]:4.类和对象中(拷贝构造+赋值运算符重载)

拷贝构造+赋值运算符重载

  • 一.拷贝构造:
    • 1.概念:
    • 2.特征:
      • 2.特征注意 ----- 浅拷贝:
      • 3.特征注意 ----- 深拷贝:
      • 4.拷贝构造的自动调用:
        • 1.内置类型:
        • 2.自定义类型:
  • 二.赋值运算符重载:
    • 1.运算符重载:
      • 1.概念引入:
      • 2.概念优化:
      • 3.概念意义:
      • 3-1:如何进行类别定义:
    • 2.日期类的运算符重载的整体代码:

一.拷贝构造:

1.概念:

拷贝构造:只有一个参数是拷贝的类类型对象,想要拷贝一个相同的类类型对象时编译器自动调用拷贝构造。

2.特征:

2-1:拷贝构造是一种特殊的构造函数,具有构造函数的所有特性 (因为构造函数允许函数重载)

2.特征注意 ----- 浅拷贝:

2-2:拷贝构造只允许有一个参数为类类形对象的引用赋值会发生无限的递归调用。
[C++ ]:4.类和对象中(拷贝构造+赋值运算符重载)_第1张图片

2-2-1:解决方法我们在传值调用的时候每次都回去进行一次拷贝构造,我们需要去避免这样的情况就需要==传引用!==不需要开辟新的空间我们只是传了一个d1日期的别名。
[C++ ]:4.类和对象中(拷贝构造+赋值运算符重载)_第2张图片

2-2-2:优化:我们这个拷贝构造函数只是用来进行拷贝,防止代码敲错我们加一个const用来限制拷贝的类类形参数:
[C++ ]:4.类和对象中(拷贝构造+赋值运算符重载)_第3张图片

2-2-3:总结:
[C++ ]:4.类和对象中(拷贝构造+赋值运算符重载)_第4张图片

3.特征注意 ----- 深拷贝:

3-1:对于前面的浅拷贝我们观察到是一种直接的拷贝但是这样的方式可以拷贝一个栈的类吗?
[C++ ]:4.类和对象中(拷贝构造+赋值运算符重载)_第5张图片

3-2:所以我们就知道栈这个类的拷贝不是简简单单的值拷贝所以我们需要显示的去进行拷贝函数的定义(在拷贝的时候开辟合适的空间并且考虑栈中的数据)
[C++ ]:4.类和对象中(拷贝构造+赋值运算符重载)_第6张图片

3-3:效果图:
[C++ ]:4.类和对象中(拷贝构造+赋值运算符重载)_第7张图片

4.拷贝构造的自动调用:

1.内置类型:

[C++ ]:4.类和对象中(拷贝构造+赋值运算符重载)_第8张图片

2.自定义类型:

这是我们实现的一个队列我们没有去显示的去定义这个队列的拷贝构造,但是因为,队列这个类是由已经显示定义好的一个栈和一个内置类型int组成我们去调用默认拷贝的时候就回去调用到栈的拷贝构造和内置类型的值拷贝了!

1.内置类型成员完成值拷贝:
2.自定义类型成员调用自己的拷贝构造:

3.总结:拷贝构造函数典型调用场景:
使用已存在对象创建新对象
函数参数类型为类类型对象
函数返回值类型为类类型对象

[C++ ]:4.类和对象中(拷贝构造+赋值运算符重载)_第9张图片

二.赋值运算符重载:

1.运算符重载:

1.概念引入:

我们知道正常的内置类型之间可以进行正常的比较,自定义类型进行比较是需要自定义函数的,因为对于任意一个自定义类型他们之间的大小比较应该由程序员自己去决定:

[C++ ]:4.类和对象中(拷贝构造+赋值运算符重载)_第10张图片

2.概念优化:

我们上面的类型比较函数是放在类的外面,外面给类的成员变量是public的,我们想要把比较的函数放到类中!
[C++ ]:4.类和对象中(拷贝构造+赋值运算符重载)_第11张图片
[C++ ]:4.类和对象中(拷贝构造+赋值运算符重载)_第12张图片

函数名字为:关键字operator后面接需要重载的运算符符号。
函数原型:返回值类型 operator操作符(参数列表)

#include
#include

using namespace std;

class date {
public:
	date(int year=10,int mouth=10 ,int day=10)
	{
		_year = year;
		_mouth = mouth;
		_day = day;
	}
	void print()
	{
		cout << _year << "-" << _mouth << "-" << _day << endl;
	}
	bool operator>(const date& y)
	{
		if (_year > y._year)
		{
			return true;
		}
		else if (_year == y._year && _mouth > y._mouth)
		{
			return true;
		}
		else if (_year == y._year && _mouth == y._mouth && _day > y._day)
		{
			return true;
		}

		return false;
	}

	bool operator==(const date& y)
	{
		return _year == y._year &&
			_mouth == y._mouth &&
			_day == y._day;
	}
private:
	int _year;
	int _mouth;
	int _day;
};


int main()
{
	date d1;
	d1.print();

	date d2(2023, 10, 21);
	d2.print();

	cout << (d1.operator>(d2)) << endl;
	cout << (d1.operator==(d2)) << endl;

	cout << (d1>d2) << endl;
	cout << (d1==d2) << endl;

	//代码报错说函数中调用的参数太少了!
	//三个形参,2个实参!

	return 0;
}

[C++ ]:4.类和对象中(拷贝构造+赋值运算符重载)_第13张图片
C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。

3.概念意义:

日期类可以实现什么运算符是取决于日期类实现什么运算符是比较有意义的:

d1 + d2
d1 - d2
d1 * d2
d1 / d3
d1 + (int)
d1 - (int)

下面主要用年月日加和加等进行运算符重载:

[C++ ]:4.类和对象中(拷贝构造+赋值运算符重载)_第14张图片

3-1:如何进行类别定义:

1.我们知道内置类型的加等的返回值是它加等之后的值,并且它本身也会被改。
2.我们知道内置类型的加返回值是它加之后的值,并且它本身也不会被更改。
3.总体来说:我们自定义类型符号操作可以类比内置类型相关操作符号的返回值!

1.我们做的是+=所以我们的返回值就是日期本身,返回值是自定义类型。但是我们为了提高效率所以使用引用返回,节省拷贝构造产生的空间时间。我们可以传拷贝构造但是为了时间和空间的节省。我们使用引用返回!
[C++ ]:4.类和对象中(拷贝构造+赋值运算符重载)_第15张图片

2.我们做的是+ ,所以我们的返回值就是一个加上的值。不需要更改日期的值只需要一个加好的日期这个自定义类型的值返回出来就可以了;这个地方必须需要传值返回!
[C++ ]:4.类和对象中(拷贝构造+赋值运算符重载)_第16张图片

2.日期类的运算符重载的整体代码:

代码较多:放在gitee下大家自取!
代码链接

你可能感兴趣的:(C++,初阶学习,1024程序员节)