流操作符 | 功能 |
---|---|
<< | 输出操作符 |
>> | 输入操作符 |
对于这两个操作符,我们如何做到重载呢???
以我们先前完成的Date类为例:
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
如果我们想要实现类似内置类型输出的形式,就需要完成操作符的重载
cout << Date类
我们先来一个简单的尝试,试试水
void operator<<(ostream& out) {
cout << _year << "年" << _month << "月" << _day << "日" << endl;
}
我们运行一下却出现了这样的报错,不匹配操作数
这是因为重载函数里面有两个参数(Date* this, ostream& out)
作为成员函数重载,this指针占据第一个参数,Date必须是左操作数!
而我们cout << d
左右参数当然不匹配,如果我们调换位置
发现可以了,但是这样十分不符合逻辑,cout 流向 a1 ???
那为了规避这个问题,我们就要把函数中参数的顺序改变,所以我们的重载就不能是成员函数。我们把重载<<作为全局函数来看呢
这时我们可以正确的输出了,但是代价是我们成员变量改为公有了,不然我们在重载<<函数无法访问成员变量,这就让我们这个类变得不够安全,所以这里使用友元来解决。
这里为了可以连续输出我们需要把函数返回值改为流,这里就可以完成连续输出。
与<<重载类似,设置友元,声明函数。
istream& operator>>(istream& in, Date& d) {
cout << "请依次输入年月日:> ";
in >> d._year >> d._month >> d._day;
}
需要注意的是日期的有效性检查。我们可以修改为:
bool Date::checkInvalid() {
if (_year <= 0 || _month < 1
|| _month>12 || _day<1
|| _day>GetMonthDay(_year, _month)) {
return false;
}
else return true;
}
istream& operator>>(istream& in, Date& d) {
cout << "请依次输入年月日:> ";
while (1) {
in >> d._year >> d._month >> d._day;
if (!d.checkInvalid()) {
cout << "输入了非法日期,请重新输入:>";
}
else break;
}
return in;
}
这样就做到了保证日期有效性的作用。
来看样例:
int main(){
const Date a1(2024,2,21);
a1.show();
return 0;
}
这里会报错:
因为我们把a1对象的权限放大了:
所以需要加入const修饰:
对于一些只读的函数,我们可以都加上const 让代码鲁棒性更加强大。
对于前面的Date类我们就可以做出完善:
#include<iostream>
using namespace std;
class Date{
public:
bool checkInvalid();
// 获取某年某月的天数
int GetMonthDay(int year, int month) const;
//展示日期
void show() const;
// 全缺省的构造函数
Date(int year = 1900, int month = 1, int day = 1);
// 拷贝构造函数
// d2(d1)
Date(const Date& d);
// 析构函数
~Date();
// 赋值运算符重载
// d2 = d3 -> d2.operator=(&d2, d3)
Date& operator=(const Date& d) const;
// 日期+=天数
Date& operator+=(int day);
// 日期+天数
Date operator+(int day) const;
// 日期-天数
Date operator-(int day) const;
// 日期-=天数
Date& operator-=(int day);
// 前置++
Date& operator++();
// 后置++
Date operator++(int);
// 后置--
Date operator--(int);
// 前置--
Date& operator--();
// >运算符重载
bool operator>(const Date& d) const ;
// ==运算符重载
bool operator==(const Date& d) const;
// >=运算符重载
bool operator >= (const Date& d) const;
// <运算符重载
bool operator < (const Date& d) const;
// <=运算符重载
bool operator <= (const Date& d) const;
// !=运算符重载
bool operator != (const Date& d) const;
// 日期-日期 返回天数
int operator-(const Date& d) const;
// 转换为字符串“ YYYY-MM-DD ”
string toString() const;
static Date fromString(const string& dateStr);
friend ostream& operator<<(ostream& out, Date& d);
friend istream& operator>>(istream& in, Date& d);
private:
int _year;
int _month;
int _day;
};
ostream& operator<<(ostream& out, Date& d);
istream& operator>>(istream& in, Date& d);
这样就让我们的代码更加完美,避免出现权限的扩大了。