个人主页:点我进入主页
专栏分类:C语言初阶 C语言进阶 数据结构初阶 Linux C++初阶 算法
欢迎大家点赞,评论,收藏。
一起努力,一起奔赴大厂
目录
一.前言
二.运算符重载
2.1概念
2.2比较的符号重载
2.2.1 operator ==
2.2.2其余的符号重载
2.3+-类实现
2.3.1operator+和operator+=的比较
2.3.2其余的符号重载
2.4前置++后置++
2.5重载<<和>>
2.6类的代码
三.const成员
四.总结
一.前言
我们在前面写了关于类的实现,这时候有人问到怎末实现类里边元素的运算呢?比如日期类我们怎末实现日期类的基本运算呢?我们知道类的成员变量是不能在类的外边进行访问的,我们就选算是想进行变量的运算也不能实现,那我们应该如何实现呢?我们可以封装成函数来实现,祖师爷对这进行了修改出现了我们的operator。那是如何实现的呢?
二.运算符重载
2.1概念
C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。函数名字为:关键字operator后面接需要重载的运算符符号。函数原型:返回值类型 operator操作符(参数列表)。
- 不能通过连接其他符号来创建新的操作符:比如operator@
- 重载操作符必须有一个类类型参数
- 用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不 能改变其含义
- 作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this
- .* :: sizeof ?: . 注意以上5个运算符不能重载。这个经常在笔试选择题中出现。
我们的类的代码为:
class Data {
public:
Data(int year = 1, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
Data(const Data& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
private:
int _year;
int _month;
int _day;
};
我们的运算符重载函数函数名放在public中,我们采用声明和定义分离的形式大致的形式,最后实现的类的代码我会在左后给出。
2.2比较的符号重载
2.2.1 operator ==
在这里我给出一个样例,后面的和这个相同,我会直接给出全部的代码,我们的代码为:
bool Data::operator==(const Data& d)
{
return _year == d._year &&
_month == d._month &&
_day == d._day;
}
这个代码是判断两个是否相同,我们运行的代码为:
Data d1(2014, 2, 5);
Data d2(d1);
d2.operator==(d1);
d2 == d1;
其中第一种是用d2的函数的形式,在设计这一块时祖师爷还支持了我们直接用==。当我们运行到这一步时会自动跳转到我们定义的函数的位置。
2.2.2其余的符号重载
bool Data::operator <(const Data& d)
{
if (_year < d._year)
return true;
else if (_year > d._year)
return false;
else
{
if (_month < d._month)
return true;
else if (_month > d._month)
return false;
else
{
if (_day < d._day)
return true;
else
return false;
}
}
}
bool Data::operator <=(const Data& d)
{
return (*this < d) || (*this == d);
}
bool Data::operator >(const Data& d)
{
return !(*this <= d);
}
bool Data::operator >=(const Data& d)
{
return !(*this < d);
}
bool Data::operator !=(const Data& d)
{
return !(*this == d);
}
看到后面是不是感觉很爽,使用的方法和上面的相同都是有两种。
2.3+-类实现
2.3.1operator+和operator+=的比较
在写代码之前我们需要知道+和+=的含义,+返回一个天数,自身不改变,+=是让本身改变,这时候我们有两种写法一种是先写+在写+=,另一种是先写+=再写+,两种方案我会一一给出,然后进行比较。
先写+再写+=代码如下:
Data Data::operator+(int day)
{
Data tmp(*this);
tmp._day += day;
while (GetMonthDay(tmp._year ,tmp._month) < tmp._day)
{
tmp._day -= GetMonthDay(tmp._year, tmp._month);
tmp._month++;
if (tmp._month == 13)
{
tmp._year++;
tmp._month = 1;
}
}
return tmp;
}
Data& Data::operator+=(int day)
{
*this = *this + day;
return *this;
}
先写+=再写+代码如下:
Data Data::operator+(int day)
{
Data tmp(*this);
tmp += day;
return tmp;
}
Data& Data::operator+=(int day)
{
_day += day;
while (GetMonthDay(_year, _month) < _day)
{
_day -= GetMonthDay(_year, _month);
_month++;
if (_month == 13)
{
_year++;
_month = 1;
}
}
return *this;
}
我们对比+,第一种用了一个临时变量,第二个用了一个临时变量,+=时左边没有用临时变量,右边用了一个,我们知道调用临时变量我们还需要调用拷贝构造,所以我们选用先写+=再写+。我们针对返回值进行解说,我们知道+应该符合连续的+比如1+2+3,所以我们的日期类应该也满足我们的连续+,1+2+3的底层是先计算2+3得到的值为一个临时变量,临时变量在和1加得到临时变量为结果,所以我们需要返回我们的Data类型,我们知道传参不如传引用快,但是由于我们返回的是一个临时变量不能传引用,因为函数结束内存释放,所以我们只能返回值(这个值会村早寄存器)。我们看+=,由于+=会改变我们的值,且返回的是我们的Data类型,所以我们采用Data&来返回引用。
2.3.2其余的符号重载
Data Data::operator-(int day)
{
Data tmp(*this);
tmp += day;
return tmp;
}
Data& Data::operator-=(int day)
{
_day -= GetMonthDay(_year, _month);
while (_day <= 0)
{
_month--;
if (_month == 0)
{
_year--;
_month = 12;
}
_day += GetMonthDay(_year, _month);
}
return *this;
}
2.4前置++后置++
我们的前置++和后置++符号都是++,我们的operator的规则是在opertaor的后面加上我们要重载的符号,由于我们的前置++后置++符号一样,所以祖师爷采用将后置++的参数部分加上一个int和前置++构成函数重载。前置--和后置--与前置++和后置++操作一样,这里不做具体解释。我们直接上代码:
Data& Data::operator++()
{
*this += 1;
return *this;
}
Data& Data::operator++(int)
{
Data tmp(*this);
*this += 1;
return tmp;
}
2.5重载<<和>>
既然支持符号重载那我们的<<和>>也应该支持,我们直接上代码:
ostream& Data::operator<< (ostream& out)
{
out << _year << "/" << _month << "/" << _day;
return out;
}
istream& Data::operator>>(istream& in)
{
in >> _year >> _month >> _day;
return in;
}
当我们写在类里面时我们想用时需要写成
d2 << cout;
d2 >> cin;
这个和我们的写法相仿,我们需要用其他的形式才行,这需要我们的友元操作,下一篇文章我会给大家进行讲解。
2.6类的代码
class Data {
public:
Data(int year = 1, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
Data(const Data& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
bool operator==(const Data& d);
bool operator <(const Data& d);
bool operator <=(const Data& d);
bool operator >(const Data& d);
bool operator >=(const Data& d);
bool operator !=(const Data& d);
int GetMonthDay(int year, int month);
Data operator+(int day);
Data& operator+=(int day);
Data operator-(int day);
Data& operator-=(int day);
Data& operator++();
Data& operator++(int);
ostream& operator<< (ostream& out);
istream& operator>>(istream& in);
private:
int _year;
int _month;
int _day;
};
三.const成员
当我们在类里面写一个print函数时我们时写成:
void Print()
{
cout << _year << "/" << _month << "/" << _day;
}
但是这是对权限的一种扩大,我们这个函数应该满足不能修改我们的值,但是这个函数却可以修改我们的值,这个时候我们出现了我们的const,应该如何写呢?我们看代码,在声明时写成:
void Print() const;
定义写为:
void Data::Print() const
{
cout << _year << "/" << _month << "/" << _day;
}
四.总结
今天的内容就结束了,主要就是对运算符的重载的详细解析,可以多体会体会其中的含义,最后希望大家可以一键三连。