赋值运算符重载–函数实现
运算符重载的意思就是我们的自己去写一个函数定义实现这里运算符的行为
运算符重载和函数重载是两个东西且没有关联
函数名:operator+运算符
- 参数:操作符的操作数有几个就有几个参数,参数类型是你要操作的类型对象
- 返回值:看运算符运算后的返回值是什么
运算符默认给内置类型变量用的, 自定义类型的变量想用运算符,得自己进行运算符重载
#include<iostream>
using namespace std;
class Date
{
public:
Date(int year = 0, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
private:
//public://用public就不会报错
int _year;
int _month;
int _day;
};
bool operator==(const Date& x1, const Date& x2)
{
//访问私有成员变量会出错
return x1._year == x2._year
&& x1._month == x2._month
&& x1._day == x2._day;
}
int main()
{
Date d1(2021, 10, 11);
Date d2(2020, 11, 11);
Date d3(2021, 11, 11);
operator==(d1, d2); // 可以这样调用但是这样调用,可读性很差,还不如写一个EqualDate函数
d1 == d2; // 自定义类型编译器转换成operator==(d1, d2);内置类型直接转换为运算符
return 0;
}
}
赋值运算符号重载(operator)写成全局的可以,但是面临访问私有成员变量的的问题,如何解决?
1、友元
2、作为成员函数放到类中
class Date
{
public:
Date(int year = 0, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
// d1 == d2; -> d1.operator==(d2); -> d1.operator==(&d1, d2);--有一个隐藏的参数
// bool operator==(Date* this, const Date& x)隐藏的this指针
bool operator==(const Date& x)
{
/*return this->_year == x._year
&& this->_month == x._month
&& this->_day == x._day;*/
return _year == x._year
&& _month == x._month
&& _day == x._day;
}
// d1 < d2;
bool operator<(const Date& x)
{
if (_year < x._year)
{
return true;
}
else if (_year == x._year && _month < x._month)
{
return true;
}
else if (_year == x._year && _month == x._month && _day < x._day)
{
return true;
}
else
{
return false;
}
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1(2021, 10, 11);
Date d2(2020, 11, 11);
Date d3(2021, 11, 11);
d1.operator==(d2);
d1 == d2; // 编译器转换成d1.operator==(d2)
d1<d2;
//因为牛插入符号<<比==符号的优先级还高,所以会先输出cout<<d1导致再遇到==时报错,所以需要加括号在d1==d2,让==先运行就不会报错
//cout << (d1 == d2) << endl;//0
//cout << (d1 < d2) << endl;//1
//cout << (d1 < d3) << endl;//1
return 0;
}
赋值运算符重载和拷贝构造
class Date
{
public:
//重载
Date(int year = 0, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
//拷贝构造
Date(const Date& d)
{
cout << "Date(const Date& d)" << endl;
_year = d._year;
_month = d._month;
_day = d._day;
}
//d1=d3
//void operator=(const Date& d)
//{
// _year = d._year;
// _month = d._month;
// _day = d._day;
//}
//d1=d2=d3,连续赋值需要返回值,d2=d3第一次返回d2,所以就是返回第一个隐函的形参this
Date& operator=(const Date& d)//d是d3的引用但const只限制别名d不限制d3
{
if (this != &d)//防止自己拷贝自己(自己拷贝自己里面的内容就没有用了),d2的地址不和d3的地址一样
{
_year = d._year;
_month = d._month;
_day = d._day;
}
return *this;//第一次返回的是d2的地址
}
void Print()
{
cout << _year << "/" << _month << "/" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1(2021, 10, 11);//d1不能为const
//d1.Print();
Date d2(2020, 11, 11);
Date d3(2021, 11, 11);//const Date d3(2021, 11, 11);d3可以为const
//1、 赋值运算符重载, 用于两个已经定义出来的对象间拷贝复制
//d1 = d3;
d1 = d2 = d3;
d1.Print();
// 自己赋值给自己
//d1 = d1;
// 2、拷贝构造,准备定义它,用另一个对象(已经存在)来初始化它
// Date d4(d3);
// d4.Print();
// Date d5 = d3; //虽然这里用了=,但是他这里是拷贝构造
return 0;
}
连续赋值
- 右操作数必须是一个已经存在的对象
如果我们不写,编译器会默认生成赋值重载
跟拷贝构造的行为类似,内置类型成员会完成值拷贝,自定义类型成员会调用他的赋值重载
class A
{
public:
A& operator=(const A& a)
{
cout << "A& operator=(const A& a)" << endl;
return *this;
}
};
class Date
{
public:
Date(int year = 0, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
Date(const Date& d)
{
cout << "Date(const Date& d)" << endl;
_year = d._year;
_month = d._month;
_day = d._day;
}
void Print()
{
cout << _year << "/" << _month << "/" << _day << endl;
}
private:
int _year;
int _month;
int _day;
A _a;//自定义类型
};
int main()
{
Date d1(2021, 10, 11);
d1.Print();
Date d2(2020, 11, 11);
Date d3(2021, 11, 11);
d1 = d2;
d1.Print();
return 0;
}
需要手动的赋值重载
- 类和对象2中写的栈–默认值拷贝和浅拷贝(内置类型)所以需要我们手动去写