C++基础——运算符重载函数讲解与练习

目录

前言:

一.运算符重载

  1.定义:

2.函数名字为:

3.函数原型:

练习:对比两个日期类对象是否相等==函数重载

练习:对比两个日期类对象>,>=的运算符重载函数

对于小于、小于等于、不等于的函数重载如下:

 练习:日期类对象+=天数的重载函数

代码如下:

 练习:日期类对象- =天数的重载函数:


前言:

class Date {
public:
	Date(int year = 1199, int month = 12, int day = 15) {
		_year = year;
		_month = month;
		_day = day;
	}
public:
	int _year;
	int _month;
	int _day;
};


int main() {
	Date d1(2022, 10, 15);
	Date d2(2022, 10, 16);

	return 0;
}

        我们都知道,在学习C语言的过程中,学过很多运算符的知识,比如:+,-,*,/,%,=,==等,它们都是用来做内置类型数据间的计算,而现在C++有了类(自定义类型),那么对于自定义类型所创建的对象,是不是也可以做这些运算呢?比如上面代码中的日期类,创建出两个对象d1,d2,那么我们是不是可以对这两个对象做运算?d1加减d2,d1是否等于d2,d1是否大或者小于d2等运算操作, 这便是我今天所要讲解的主题了——运算符重载函数,它是类的另一大特殊成员函数。

一.运算符重载

  1.定义:

        C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似它主要是针对自定义类型做运算而研发的。

2.函数名字为:

        关键字operator后面接需要重载的运算符符号。

3.函数原型:

        返回值类型  operator操作符(参数列表)

        

         1. 不能通过连接其他符号来创建新的操作符:比如operator@

          2.重载操作符必须有一个类类型参数 用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不能改变其含义 。

        3.作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this

        4.   .*运算符、::运算符、sizeof运算符、?:运算符、 .运算符这五种运算符不支持运算重载!!!

练习:对比两个日期类对象是否相等==函数重载
 

class Date {
public:
	Date(int year = 1199, int month = 12, int day = 15) {
		_year = year;
		_month = month;
		_day = day;
	}
public:
	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);
}

int main() {
	Date d1(2022, 10, 15);
	Date d2(2022, 10, 16);

	cout << (d1 == d2 )<< endl;	
	return 0;
}

        解析:通过创建日期类对象d1,d2去比较他俩是否相等,operator处在类外,因为日期类的成员全都是公共成员,所以类外的函数可以轻易的访问到类内。

                重载函数operator==是通过比较两个对象的成员变量,通过布尔类型去判定返回真假值。

                d1==d2是隐式调用重载函数operator==的写法,它等价于d1.operator(d2);这句是显式调用,但我们一般不这么写。注:d1==d2要给括号,因为cout<<会有优先级问题!

若日期类中的成员是私有的,那又该怎么办?

这时,我们可以把重载函数放进类内处理,但需要改变函数的形参:

class Date {
public:
	Date(int year = 1199, int month = 12, int day = 15) {
		_year = year;
		_month = month;
		_day = day;
	}
	//将重载函数放在类里面
	bool operator==(const Date& d) {
		return (_year == d._year && _month == d._month && _day == d._day);
	}

private:
	int _year;
	int _month;
	int _day;
};

int main() {
	Date d1(2022, 10, 15);
	Date d2(2022, 10, 16);
	cout << (d1 == d2) << endl;	//d1==d2要加括号,否则会引发优先级问题
	return 0;
}

        形参d就代表是d2,_year,_month,_day都是d1的成员变量。


练习:对比两个日期类对象>,>=的运算符重载函数


class Date {
public:
	Date(int year = 1199, int month = 12, int day = 15) {
		_year = year;
		_month = month;
		_day = day;
	}

	//比较大小——重载
	bool operator>(const Date& d) {
		if (_year > d._year) {
			return true;
		}
		else if (_year == d._year && _month > d._month) {
			return true;
		}
		else if (_year == d._year && _month == d._month && _day > d._day) {
			return true;
		}
		else {
			return false;
		}
	}

private:
	int _year;
	int _month;
	int _day;
};

int main() {
	Date d1(2022, 10, 22);
	Date d2(2022, 9, 25);
	cout << (d1 > d2) << endl;
}

        operator>重载函数中,需要逐年、逐月、逐日的去判定大小! 

class Date {
public:
	Date(int year = 1199, int month = 12, int day = 15) {
		_year = year;
		_month = month;
		_day = day;
	}

bool operator>=(const Date& d) {
		if (_year > d._year) {
			return true;
		}
		else if (_year == d._year && _month > d._month) {
			return true;
		}
		else if (_year == d._year && _month == d._month && _day >= d._day) {
			return true;
		}
		else {
			return false;
		}
	}
    private:
	int _year;
	int _month;
	int _day;
};

对于大于等于的函数重载,只需要在day上加个=即可,但代码可读性不高,其实我们可以复用operator>的函数重载:

bool operator>=(const Date& d) {	    //d是d2,*this是d1
		return (*this > d || *this == d);
		
	}

解析:*this>d 会调用运算符重载函数operator>,*this==d会调用运算符重载函数operator== 

        这种写法代码复用性很高,一步就可以解决。

对于小于、小于等于、不等于的函数重载如下:

//判定小于的运算符重载函数
	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);
	}

 练习:日期类对象+=天数的重载函数

        对于月份天数的运算,首先要搞清楚每个月有几天,特殊年——闰年2月的天数,相加该怎么加。

        算法如图:每当要加的天数超过本月的最大值时,先加起来,然后减去该月的最大值,让其月份+1即可;对于12月来说,若相加的天数超过30天,那么就会到下一年,我们应该让月份归一,年份+1即可;对于2月,还得判定它是否是闰年的二月!得考虑众多情况。

代码如下:

class Date {
public:
	Date(int year = 1199, int month = 12, int day = 15) {
		_year = year;
		_month = month;
		_day = day;
	}

	//判定月份天数
	int GetMonthDay(int year, int month) {
		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& operator+=(int day) {
		_day += day;
		while (_day > GetMonthDay(_year, _month)) {
			_day -= GetMonthDay(_year, _month);
			_month++;
			if (_month == 13) {
				_month = 1;
				_year++;
			}
		}
		return *this;
	}

	void Print() {
		cout << _year << "-" << _month << "-" << _day << endl;
	}

private:
	int _year;
	int _month;
	int _day;
};

int main() {
	Date d1(2022, 10, 22);
	Date d2(2022, 9, 23);
	d1 += 5;
	d1.Print();
	d1 += 10;
	d1.Print();
	d1 += 50;
	d1.Print();
	d1 += 100;
	d1.Print();
	return 0;
}

        先获取到每个月的天数,对于闰年二月要做特殊处理,其次就是在重载函数中进行算法编写;最后需要注意一点,传值返回会多进行一次拷贝,为了提高运行效率,应该用引用返回。

        而对于operator+重载函数来说,+并不会改变对象,在内置类型中,int a=10;a+10;也照样不会改变变量a的值,只是a+10的返回值是15,所以针对+的重载函数,我们应该用值传递

Date operator+(int day) {
		Date ret(*this);	//调用拷贝构造
		ret += day;
		return ret;
	}

        Date ret(*this)语句会调用该类的拷贝构造函数,也就是说新对象ret会拷贝对象d2的数据,ret虽然+=day了,但这是值传递,形参的改变并不会影响实参,所以d2并不会被改变。 

 练习:日期类对象- =天数的重载函数:

        算法如图:核心思想是借位。先减去天数,若日期小于等于0,则需要去借上个月的最大天数,用于弥补日期的负值,直到补正为止。

Date&  operator-=(int day) {
		_day -= day;
		while (_day <= 0) {
			_month--;
			if (_month == 0) {
				_month = 12;
				_year--;
			}
			_day += GetMonthDay(_year, _month);
		}
		return *this;
	}
	Date  operator-(int day) {
		Date ret(*this);//拷贝构造
		ret -= day;
		return ret;
	}

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

橙予清的zzz~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值