赋值运算符重载
运算符重载
不能通过连接其他符号来创建新的操作符,如:operator@
重载操作符必须有一个类类型参数
用于内置类型的运算符,其含义不能改变,如,内置类型的+,不能改变含义
最为类成员函数重载时,其形参看起来比操作数目少1,因为成员函数的第一个参数为隐藏的this
.* :: sizeof ?: . 这五个运算符不能重载。
上面代码中重载了一个全局的operator==,但是全局要求成员变量是公有的,这就牵扯到一个问题,如何保证封装性?
提供可以获取到成员变量的成员函数
使用友元(后面将会学习)
重载成成员函数
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
// bool operator==(Date* this, const Date& d2)
// 这里需要注意的是,左操作数是this,指向调用函数的对象
bool operator==(const Date& d2)
{
return _year == d2._year
&& _month == d2._month
&& _day == d2._day;
}
private:
int _year;
int _month;
int _day;
};
上面的代码就成功将==操作符重载成了成员函数,在使用时与全局的==并无区别。
赋值运算符重载
经过上面对操作符重载的简单介绍,赋值重载简单说就是字面意思,重载了=这一符号,使其可以用于对象之间的相互赋值。
- 赋值运算符重载格式
参数类型:const T&,传引用提高效率
返回值类型:T& 返回引用可以提高返回效率,有返回值的目的是为了支持连续赋值
检测是否给自己赋值
返回*this:要符合连续赋值的含义
代码示例(完整的赋值运算符重载):
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;
};
- 赋值运算符只能重载成类的成员函数不能重载成全局函数
- 用户没有显式实现时,编译器会生成一个默认赋值运算符重载,以值的方式逐字节拷贝。注意:内置类型成员变量是直接赋值的,而自定义类型成员变量需要调用对应类的赋值运算符重载完成赋值。虽然编译器生成的默认赋值运算符可以完成字节序的值拷贝,但一旦涉及到资源的管理时,编译器生成的依然是不够用的,原因和默认生成的拷贝构造函数类型。
再次对拷贝构造和赋值运算符重载做一个区分,两个函数虽然都可以用 = 拷贝复制现有的一个对象,但使用等于时的情形是完全不同的。以日期类为例:
//拷贝构造
Date d2 = d1;
//复制运算符重载
Date d2;
d2 = d1;
结语
本篇博客主要讲了拷贝构造函数和赋值运算符重载,它们在类中扮演着至关重要的角色,是对象复制和赋值操作的基础,确保对象在复制和赋值过程中保持正确的状态和行为。如果没有正确地实现这两个函数,可能会导致数据不一致、内存泄漏或其他严重问题。因此,在编写自定义类时,通常需要仔细考虑是否需要显式定义拷贝构造函数和赋值运算符重载,并根据类的具体需求来实现它们。对于某些类(如包含动态分配内存的类),显式定义这两个函数是必不可少的。下篇博客将会讲到最后两个类的默认成员函数,以及操作符重载更多的使用情境。
本篇博客到此结束,感谢大家的支持!♥