在之前的学习过程中,我们遇到了关于运算符重载的相关知识(出现于类的六个默认成员函数中赋值运算符重载,详细可参考上期博客C++入门基础(五) 类的六个默认成员函数详解),在那里我们知道了什么 叫运算符重载,为什么要重载?重载的功能是什么?但是其具体该如何运用呢?本篇博客中我们将通过一个日期类的示例具体进行学习。
运算符重载
运算符重载概念
在C++面向对象的语言中,允许在同一作用域中的某个运算符指定多个定义,我们称之为运算符重载,此时当我们再次调用重载运算符时,编译器通过该运算符使用场景中所携带的参数类型与定义中的参数类型进行比较,决定选用最合适的定义。选择最合适的重载运算符的过程,称为重载决策。从而完成不同类型下相关运算符操作的处理,增加代码的可读性
运算符重载的写法格式
运算符重载我们可以看做是具有特殊函数名的函数,与一般函数一样,其同样具有返回值类型、函数名称以及参数列表、函数体。
函数名:operator+需要重载的运算符
函数表达式:返回值类型 +operator+需要重载的运算符+(参数列表)
运算符重载的操心点
- 不能通过连接其他符号来创建新的操作符:比如operator@,其表示只能对已知的运算符功能进行扩展重写,但是不能凭空创造。
- 重载操作符必须有一个类类型或者枚举类型的操作数
- 用于内置类型的操作符,其含义不能改变,例如:内置的整型+,不能改变其含义,以避免产生误用
- 作为类成员的重载函数时,其形参看起来比操作数数目少1成员函数的操作符有一个默认的形参this,限定为第一个形参,在类外定义时要将所用的参数一一列出。
- .* 、:: 、sizeof 、?: 、. 注意以上5个运算符不能重载。
日期类的相关运算符实现
class Date//日期类
{
public:
Date(int y = 1, int m = 1, int d = 1)//构造全缺省默认成员函数
{
//判断日期是否有效,一共12个月
if (y <= 0 || m <= 0 || m > 12
|| d <= 0 || d > getDay(y, m))
{
this->_d = 1;
this->_m = 1;
this->_y = 1;
cout << "日期无效,设为默认值1-1-1" << endl;
}
else
{
this->_d = d;
this->_m = m;
this->_y = y;
}
}
int getDay(int y, int m)//获取年月,主要判断特殊月份二月的天数
{
static int days[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
int day = days[m];
if (m == 2)
{
if (y % 4 == 0 && y % 100 != 0 || y % 400 == 0)
day++;
}
return day;
}
private:
int _y;
int _m;
int _d;
};
之后在类中重定载各种功能运算符,注意内置的函数中包含默认参数的*this。以及其返回值类型,根据运算符具体意义而定。
//日期运算
//Date+=int
Date& operator+=(int day)//在对象上使用+=,类比a+=1--->a=a+1需要改变自身值,因此返回值类型为引用,避免对象的传值,提高性能
{
//判断日期是否为负数,若为负数,调用-=操作符
if (day<0)
return *this -= -day;
_d = _d + day;
while (_d > getDay(_y, _m))//判断当前月份天数是否越界
{
_d = _d - getDay(_y, _m);
_m++;
if (_m > 12)//判断当前月份是否越界,越界增加年数
{
_m = _m - 12;
_y++;
}}
return *this;//返回对象
}
//前置++,++操作符需要进行区分,前置++是先进行自加运算再使用,而后置++是先使用对象再自加,
//++Date
Date& operator++()
{
*this += 1;
return *this;//前置++直接返回当前对象
}
//后置++
Date operator++(int)
{
Date d2(*this);
*this += 1;
return d2;//返回原来的对象,对当前对象进行自加
}
Date operator+(int day)//+对原对象的基础上+1返回,但对象本身不发生改变
{
Date d2(*this);
return d2 += day;//返回拷贝构造的新临时对象
}
Date& operator-=(int day)//构建规则与+=相似,知识功能相反
{//判断日期0是否为负数
if (day < 0)
return *this += -day;
_d = _d - day;
while (_d <= 0)
{
if (_m == 1)
{
_m = 12;
_y = _y - 1;
}
else
_m = _m - 1;
int day1 = getDay(_y, _m);
_d = day1 + _d;
}
return *this;
}
Date operator-(int day)//其构建规则与+相似,功能相反
{
Date d2(*this);
return d2 -= day;
}
Date& operator--()//其构建规则与++相似,功能相反
{
*this -= 1;
return *this;
}
Date operator--(int)
{
Date d2(*this);
*this -= 1;
return d2;
}
Date& operator=(const Date& dt)//其中隐含了Date *this指针参数,用于接收符号左边的参数
{
if(this != &d)/判断是否是同一个对象,若不是同一个对象则进行赋值
{
_year=dt._year;
_month=dt._month;
_day=dt._day;
}
return *this; //返回对象本身作为引用接收
}
bool operator==(const Date& d)//判断两个对象的成员函数是否相等
{
return _y == d._y&&_m == d._m&&_d == d._d;
}
bool operator!=(const Date& d)//除去==的所有情况
{
return !(*this==d);
}
bool operator>(const Date& d)//年月日大小依次相比
{
if (_y > d._y)
return true;
else if (_y == d._y)
{
if (_m > d._m)
return true;
else if (_m == d._m)
{
if (_d > d._d)
return true;
}
}
return false;
}
bool operator>=(const Date& d)//>或者==的情况,调用这两个重载函数
{
return *this > d || *this == d;
}
bool operator<=(const Date& d)//<或者==的情况,调用这两个重载函数
{
return !(*this > d);
}
bool operator<(const Date& d)//除了>=之外的所有情况
{
return !(*this >= d);
}
//日期相减:Date-Date
int operator-(const Date& d)
{
//计算比较小的日期自加多少次等于较大的日期,自加的次数就是相差的天数
Date min(*this);
Date max(d);
int day = 0;
int flag = 1;
if (min > max)
{
min = d;
max = *this;
flag = -1;
}
while (min < max)
{
++min;
day++;
}
return flag*day;
}
int getyear()
{
return _y;
}
int getmonth()
{
return _m;
}
int getday()
{
return _d;
}
这样以来,基本的日期类运算功能均可基于以上运算符重载进行实现。
欢迎各位批评指正,共同进步。

513

被折叠的 条评论
为什么被折叠?



