一operator,运算符的重载
C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其 返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。 函数名字为:关键字operator后面接需要重载的运算符符号。 函数原型:返回值类型 operator操作符(参数列表)
注意:
- 不能通过连接其他符号来创建新的操作符:比如operator@
- 重载操作符必须有一个类类型参数
- 用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不 能改变其含义
- 作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐 藏的this
- .* :: sizeof ?: . 注意以上5个运算符不能重载。这个经常在笔试选择题中出 现。
1运算符的重载
// 全局的operator==
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;
};
// 这里会发现运算符重载成全局的就需要成员变量是公有的,那么问题来了,封装性如何保证?
// 这里其实可以用我们后面学习的友元解决,或者干脆重载成成员函数。
bool operator==(const Date& d1, const Date& d2)
{
return d1._year == d2._year
&& d1._month == d2._month
&& d1._day == d2._day;
}
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
// bool operator==(Date* this, const Date& d2)
// 这里需要注意的是,左操作数是this,指向调用函数的对象
bool operator==(const Date& d2)
{
return _year == d2._year;
&& _month == d2._month
&& _day == d2._day;
}
private:
int _year;
int _month;
int _day;
};
void Test ()
{
Date d1(2018, 9, 26);
Date d2(2018, 9, 27);
cout<<(d1 == d2)<<endl;
}
上面是两种方式
- 代码一是在全局上定义bool operator==(const Date&d1,const Date &d2) 较为方便
- 代码二是在类里面定义运算符函数,所以有一个隐含的this指针在前面,在Test的测试中this代表了d1的形参
2赋值运算符的重载
2.1赋值运算符重载格式
- 参数类型:const T&,传递引用可以提高传参效率 返回值类型:T&,
- 返回引用可以提高返回的效率,有返回值目的是为了支持连续赋值
- 检测是否自己给自己赋值
- 返回*this :要复合连续赋值的含义
class Date
{
public :
Date(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
Date (const Date& d)//提高效率传引用
{
_year = d._year;
_month = d._month;
_day = d._day;
}
Date& operator=(const Date& d)
{
if(this != &d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
return *this;
}
private:
int _year ;
int _month ;
int _day ;
};
2.2 赋值运算符只能重载成类的成员函数不能重载成全局函数
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
int _year;
int _month;
int _day;
};
// 赋值运算符重载成全局函数,注意重载成全局函数时没有this指针了,需要给两个参数
Date& operator=(Date& left, const Date& right)
{
if (&left != &right)
{
left._year = right._year;
left._month = right._month;
left._day = right._day;
}
return left;
}
原因:赋值运算符如果不显式实现,编译器会生成一个默认的。此时用户再在类外自己实现 一个全局的赋值运算符重载,就和编译器在类中生成的默认赋值运算符重载冲突了,故赋值 运算符重载只能是类的成员函数。
2.3. 用户没有显式实现时,编译器会生成一个默认赋值运算符重载,以值的方式逐字节拷贝
注 意:内置类型成员变量是直接赋值的,
而自定义类型成员变量需要调用对应类的赋值运算符 重载完成赋值。
typedef int DataType;
class Stack
{
public:
Stack(size_t capacity = 10)
{
_array = (DataType*)malloc(capacity * sizeof(DataType));
if (nullptr == _array)
{
perror("malloc申请空间失败");
return;
}
_size = 0;
_capacity = capacity;
}
void Push(const DataType& data)
{
// CheckCapacity();
_array[_size] = data;
_size++;
}
~Stack()
{
if (_array)
{
free(_array);
_array = nullptr;
_capacity = 0;
_size = 0;
}
}
private:
DataType *_array;
size_t _size;
size_t _capacity;
};
int main()
{
Stack s1;
s1.Push(1);
s1.Push(2);
s1.Push(3);
s1.Push(4);
Stack s2;
s2 = s1;
return 0;
}
注意:如果类中未涉及到资源管理,赋值运算符是否实现都可以;一旦涉及到资源管理则必
须要实现。具体原因涉及深拷贝和浅拷贝,会free两次空间,看
3前置++,后置++
前置++Date &operator++()
后置++Date&operaotr++(int)是固定格式,在c++中是需要记住的
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
// 前置++:返回+1之后的结果
// 注意:this指向的对象函数结束后不会销毁,故以引用方式返回提高效率
Date& operator++()
{
_day += 1;
return *this;
}
// 后置++:
// 前置++和后置++都是一元运算符,为了让前置++与后置++形成能正确重载
// C++规定:后置++重载时多增加一个int类型的参数,但调用函数时该参数不用传递,编译器
自动传递
// 注意:后置++是先使用后+1,因此需要返回+1之前的旧值,故需在实现时需要先将this保存
一份,然后给this+1
// 而temp是临时对象,因此只能以值的方式返回,不能返回引用
Date operator++(int)
{
Date temp(*this);
_day += 1;
return temp;
}
private:
int _year;
int _month;
int _day;
};
二日期类的实现
#pragma once
#include<iostream>
using namespace std;
#include<assert.h>
class Date {
public:
Date(int year = 1900, int month = 1, int day = 1);
void printf();
bool operator<(const Date& d);
bool operator>(const Date& d);
bool operator<=(const Date& d);
bool operator>=(const Date& d);
bool operator==(const Date& d);
Date operator+=(int day);
Date operator-(int day);
bool operator!=(const Date& d);
//前置
Date &operator++();
//后置特殊处理
Date operator++(int);
Date& operator--();
Date operator--(int);
Date operator-=(int day);
Date operator+(int day);
int operator-(const Date& d);
void operator<<(ostream& out);
int getday(int year, int month)//
{
static int monthday[13] = {
-1,31,29,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];
}
private:int _year;
int _month;
int _day;
};
#include"Date.h"
Date::Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
void Date::printf()
{
cout << _year << " " << _month << " " << _day << endl;
}
bool Date::operator<(const Date& d)
{ if (d._year > _year)
{
return true;
}
else if (d._year == _year)
{
if (d._month == _month)
{
if (d._day > _day)
{
return true;
}
}
else if (d._month >_month)
{
return true;
}
}
return false;
}
bool Date:: operator!=(const Date& d)
{
return !(*this == d);
}
bool Date::operator==(const Date& d)
{
return d._year == _year && d._month ==_month && d._day == _day;
}
bool Date ::operator<=(const Date& d)
{
return *this <d||*this==d;
}
bool Date::operator>(const Date& d)
{
return !(*this <= d);
}
bool Date ::operator>=(const Date& d)
{
return !(*this < d);
}
Date Date::operator+=(int day)
{
if (day < 0)
{
return *this -=-day;
}
_day += day;
while (_day >getday(_year, _month))
{
_day -= getday(_year, _month);
_month++;
if (_month > 12)
{
_year++;
_month = 1;
}
}
return *this;
}
//先减所有天数,再将前一个月(和加法不同)的天数抵消,其中有月尾0的情况
Date Date::operator-=(int day)
{
_day -= day;
while (_day <=0)
{
_month--;
if (_month<1)
{
_year--;
_month = 12;
}
_day += getday(_year, _month);
}
return *this;
}
Date Date::operator-(int day)
{
Date tem = *this;
tem-=day;
return tem;
}
Date Date:: operator+(int day)
{
Date tem = *this;
tem += day;
return tem;
}
Date& Date:: operator++()
{
*this += 1;
return *this;
}
Date Date :: operator++(int )//定义
{
Date tem(*this);
*this+=1;
return tem;
}
Date& Date:: operator--()
{
*this -= 1;
return *this;
}
Date Date:: operator--(int)
{
Date tem(*this);
tem -= 1;
return tem;
}
int Date ::operator-(const Date& d)
{
Date min = d;
Date max = *this;
int flag = 1;
if (*this<d)
{
min = *this;
max = d;
flag = -1;
}
int day = 0;
while (min!=max)
{
++min;
day++;
}
return day*flag;
}
void Date:: operator<<(ostream& out)
{
out << _year << "年" << _month << "月" << _day << "日" << endl;
}
创作不易希望支持!!!