1.运算符重载的意义
C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。
函数名字为:关键字operator后面接需要重载的运算符符号。
函数原型:返回值类型 operator操作符(参数列表)
当您调用一个重载函数或重载运算符时,编译器通过把您所使用的参数类型与定义中的参数类型进行比较,决定选用最合适的定义。选择最合适的重载函数或重载运算符的过程,称为重载决策。
在同一个作用域内,可以声明几个功能类似的同名函数,但是这些同名函数的形式参数(指参数的个数、类型或者顺序)必须不同。您不能仅通过返回类型的不同来重载函数。
注意:
- 不能通过连接其他符号来创建新的操作符:比如operator@
- 重载操作符必须有一个类类型参数
- 用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不 能改变其含义
- 作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this
- .* sizeof ?: . :: #注意以上6个运算符不能重载。切记
2.运算符重载的使用
通过实现一个日期类函数,学习运算符重载的使用
先来写一个类用来实现日期类的创建
class Date
{//友元函数friend ostream& operator<<(ostream& out, const Date& date);friend ostream& operator>>(istream& in, Date& date);
public:Date(int year = 0, int month = 0, int day = 0){_year = year;_month = month;_day = day;cout << "创建" << _year << endl;}~Date(){cout << "销毁" << _year << endl;}//拷贝构造函数Date(Date& date){cout << "1" << endl;_year = date._year;_month = date._month;_day = date._day;}//void Print();//判断两个日期是否相等bool operator==(const Date& days);//判断前一个日期是否大于等于后一个日期bool operator>=(const Date& days);//判断前一个日期是否小于等于后一个日期bool operator<=(const Date& days);//判断前一个日期是否大于后一个日期bool operator>(const Date& days);//判断前一个日期是否小于后一个日期bool operator<(const Date& days);//判断两个日期是否不相等bool operator!=(const Date& days);//日期加一个天数,返回一个日期,改变原日期Date& operator+=(int days);//日期加一个天数,返回另一个日期,原日期不变Date operator+(int days);//日期减天数,返回一个日期,原日期改变Date& operator-=(int days);//日期减日期,返回一个天数int operator-=(Date& days);Date& operator--();Date& operator--(int) ;Date& operator++();Date& operator++(int) ;private:int _year;int _month;int _day;
};//重载流提取
ostream& operator<<(ostream& out, const Date& date);
//重载流插入
ostream& operator>>(istream& in, Date& date);
3.友元函数:(临时插入)
类的友元函数是定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员。尽管友元函数的原型有在类的定义中出现过,但是友元函数并不是成员函数。
友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类,在这种情况下,整个类及其所有成员都是友元。
如果要声明函数为一个类的友元,需要在类定义中该函数原型前使用关键字 friend。
注意:友元提供了一种突破封装的方式,有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不宜多用。
说明:
- 友元函数可访问类的私有和保护成员,但不是类的成员函数
- 友元函数不能用const修饰
- 友元函数可以在类定义的任何地方声明,不受类访问限定符限制
- 一个函数可以是多个类的友元函数
- 友元函数的调用与普通函数的调用原理相同
友元类下次再说
4.日期类函数的实现
4.1打印函数
/打印函数,用下面的流插入流体取实现
//void Date::Print()
//{
// cout << _year << " "
// << _month << " "
// << _day << endl;
//}
4.2 比较运算符的实现
//相等
bool Date::operator==(const Date& days) const
{return _year == days._year &&_month == days._month &&_day == days._day;
}
//大于
bool Date::operator>(const Date& days) const
{if (_year > days._year){return true;}else if (_year == days._year &&_month > days._month){return true;}else if (_year == days._year &&_month == days._month &&_day > days._day){return true;}return false;
}
//小于
bool Date::operator<(const Date& days) const
{return !(*this > days && *this == days);
}
//大于等于
bool Date::operator>=(const Date& days) const
{return (*this > days)|| (*this == days);
}
//小于等于
bool Date::operator<=(const Date& days) const
{return !(*this > days);
}
//不等于
bool Date::operator!=(const Date& days) const
{return !(*this == days);
}
4.3加减法的实现
//判断一个月的天数
int GetMonthDay(int _year, int _month)
{static int monthday[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };if (_month == 2&& ((_year % 4 == 0) && (_year % 100 != 0 )|| (_year % 400 == 0)))//判断闰年{return 29;}return monthday[_month];
}
//日期加一个天数
Date& Date::operator+=(const int days)
{_day += days;while (_day > GetMonthDay(_year, _month)){_day -= GetMonthDay(_year, _month);_month++;if (_month == 13){_year++;_month = 1;}}return *this;
}
//日期加天数,本身不变
Date Date::operator+(const int days)
{Date tmp(*this);tmp += days;return tmp;
}
//日期减天数,本身改变
Date& Date::operator-=(int days)
{if (days < _day){_day -= days;return *this;}else if (days == _day){_month -= 1;if (_month == 0){_month = 12;_year--;}_day = GetMonthDay(_year, _month);return *this;}else{days -= _day;_month -= 1;if (_month == 0){_month = 12;_year -= 1;}while (days > GetMonthDay(_year, _month)){_month -= 1;if (_month == 0){_month = 12;_year -= 1;}}return *this;}}
Date Date::operator-(int days)
{Date tmp(*this);tmp -= 1;return tmp;
}
//日期减日期
int Date::operator-=(Date& days)
{//int days = 0;if (*this > days){if(_day>days._day)return _day - days._day;else{return _day + GetMonthDay(_year, _month - 1) - days._day;}}else if (*this == days){return 0;}else{if (_day < days._day)return days._day-_day;else{return days._day+ GetMonthDay(_year, _month - 1) - _day;}}}
//前置日期减减
Date& Date::operator--()
{*this -= 1;return *this;
}
//后置减减,后置加加需要传一个int,语法规定,后置加加也一样
Date& Date::operator--(int)
{Date tmp(*this);tmp -= 1;return *this;
}
//前置加加
Date& Date::operator++()
{*this += 1;return *this;
}
//后置加加
Date& Date::operator++(int)
{Date tmp(*this);tmp += 1;return *this;
}
4.4流提取和流插入
//流插入 ostream& operator<<(ostream& out, const Date& date) {out << date._year << "年"<< date._month << "月"<< date._day << "日"<< endl;return out; } //流提取 ostream& operator>>(istream& in, Date& date) {in >> date._year >> date._month >> date._day;return cout<<date; }
这是运算符重载和重载函数的实现,有兴趣的可以自己敲一下。