简谈struct 运算符重载

其实是在做PAT的Cars on Campus (30)这道题,一直想用struct重载做出来,折腾了好久,也不知道问题出在哪里。

一:本文要实现的目标

     1.定义一个时间的结构体

     2.对这个结构体进行<+-,=以及输出<<运算符的重载

struct Inf
{
	int hh, mm, ss;
	string inOrOut;
	Inf(){}
	Inf(int _hh, int _mm, int _ss) :hh(_hh), mm(_mm), ss(_ss){}
}
其中inOrOut是那道题目的一个标志的信息,先不用管它,其他参数分别是时分秒。

二:重载的细节

     1.对于<

bool operator< (const Inf r)const { return hh * 3600 + mm * 60 + ss < r.hh * 3600 + r.mm * 60 + r.ss; }

可能大家开始跟我一样,对这行代码一脸的无语,不知道是啥,解释下,bool为函数类型,operator<一起为函数的名字(const Inf r)定义了一个不可以修改的参数,大括号{}里面是返回值,这样是不是好看多了                        。

这里有个问题,我前几天用这个方法和另外一种方法实现了对vector<Inf> a 这个容器的排序,但是这里实现不了,只能做比较。容我比较下原来的代码再把这部分加进来。

   2.对于-和+

Inf operator - (Inf& r)
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>int h, m, s;
<span style="white-space:pre">		</span>string inOO;
<span style="white-space:pre">		</span>if (ss<r.ss)
<span style="white-space:pre">		</span>{
<span style="white-space:pre">			</span>s = ss + 60 - r.ss;
<span style="white-space:pre">			</span>mm--;
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>else
<span style="white-space:pre">			</span>s = ss - r.ss;
<span style="white-space:pre">		</span>if (mm<r.mm)
<span style="white-space:pre">		</span>{
<span style="white-space:pre">			</span>m = mm + 60 - r.mm;
<span style="white-space:pre">			</span>hh--;
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>else
<span style="white-space:pre">			</span>m = mm - r.mm;
<span style="white-space:pre">		</span>h = hh - r.hh;
<span style="white-space:pre">		</span>return Inf(h, m, s);
<span style="white-space:pre">	</span>}
同样,这里返回值是inf的结构,operator+为函数名,(inf& r)为参数,然后{}里面是内容。

这里千万提醒一点,千万不能返回引用&的类型,具体原因我看了http://www.cnblogs.com/Mr-xu/archive/2012/08/07/2626973.html 后还是不大清楚,但是却真真确确体会到不能返回值不能为引用类型的,例如,如果代码写成这样,会出现这样的错误。

错误代码:

	Inf& operator +(Inf& r){
		int h, m, s;
		if (ss + r.ss >= 60)
		{
			s = ss + r.ss - 60;
			mm++;
		}
		else
			s = ss + r.ss;
		if (mm + r.mm >= 60)
		{
			m = mm + r.mm - 60;
			hh++;
		}
		else
			m = mm + r.mm;
		h = hh + r.hh;
		return Inf(h, m, s);
	}
报错:

  3.对于=

代码:

	Inf& operator =(Inf& r)
	{
		hh = r.hh;
		mm = r.mm;
		ss = r.ss;
		return *this;
	}
这里返回值就要是引用行了,按照这篇博客的说法( http://www.cnblogs.com/Mr-xu/archive/2012/08/07/2626973.html) 就是=可以连续赋值来使用,例如x=j=10;这样俩个=符合的返回值不同,就必须在新构造一个对象,假如用指针(*=)又破坏了一致性,所以这个时候只能用引用了。 this为指针,类型为引用型,所以要节引用即*this。
  4.对于<<

   4.1先要在struct结构体内部对 ostream<< 友元

friend ostream &operator<<(ostream &out, Inf r);
 其中friend 为友元符号,ostream 为类型 operator<<为 函数名(opstream &out,Inf r)为参数

结构体外面,对函数进行完善,代码为:

ostream& operator<<(ostream &out, Inf r)
{
	if (r.hh < 10)
		out << 0 << r.hh;
	else
		out << r.hh;
	out << ":";
	if (r.mm < 10)
		out << 0 << r.mm;
	else
		cout << r.mm;
	out << ":";
	if (r.ss < 10)
		out << 0 << r.ss;
	else
		out << r.ss;
	return out;
}
这里我们可以看出,返回值也是友元型,因为<<也经常会有连用的现象,例如cout<<a<<endl;a和endl明显不是一个类型,所以还是同样的原理,只能用&。

三:struct运算符重载的实现

代码:

#include<iostream>
#include<vector>
#include<string>
#include<deque>
#include<algorithm>
using namespace std;
struct Inf
{
	int hh, mm, ss;
	string inOrOut;
	Inf():inOrOut(){}
	Inf(int _hh, int _mm, int _ss) :hh(_hh), mm(_mm), ss(_ss){}
	bool operator < (const Inf r)const { return hh * 3600 + mm * 60 + ss < r.hh * 3600 + r.mm * 60 + r.ss; }
	Inf operator - (Inf& r)
	{
		int h, m, s;
		string inOO;
		if (ss<r.ss)
		{
			s = ss + 60 - r.ss;
			mm--;
		}
		else
			s = ss - r.ss;
		if (mm<r.mm)
		{
			m = mm + 60 - r.mm;
			hh--;
		}
		else
			m = mm - r.mm;
		h = hh - r.hh;
		return Inf(h, m, s);
	}
	Inf& operator +(Inf& r){
		int h, m, s;
		if (ss + r.ss >= 60)
		{
			s = ss + r.ss - 60;
			mm++;
		}
		else
			s = ss + r.ss;
		if (mm + r.mm >= 60)
		{
			m = mm + r.mm - 60;
			hh++;
		}
		else
			m = mm + r.mm;
		h = hh + r.hh;
		return Inf(h, m, s);
	}
	Inf& operator =(Inf& r)
	{
		hh = r.hh;
		mm = r.mm;
		ss = r.ss;
		return *this;
	}
	friend ostream &operator<<(ostream &out, Inf r);
};
ostream& operator<<(ostream &out, Inf r)
{
	if (r.hh < 10)
		out << 0 << r.hh;
	else
		out << r.hh;
	out << ":";
	if (r.mm < 10)
		out << 0 << r.mm;
	else
		cout << r.mm;
	out << ":";
	if (r.ss < 10)
		out << 0 << r.ss;
	else
		out << r.ss;
	return out;
}

int main()
{
	Inf a1 = Inf(13, 56, 57);
	Inf a2 = Inf(06, 30, 58);
	vector<Inf> a;
	a.push_back(a1);
	a.push_back(a2);
	
	Inf a3 = a1 - a2;
	//Inf a3 = a1 + a2;
	a.push_back(a3);
	sort(a.begin(), a.end());
	for (int i = 0; i < a.size(); i++)
	{
		cout << a[i] << endl;
	}
	return 0;
}

结果图:


这里其实用到了所有的重载项,还用sort对vector<Inf> a 进行了排序,所以看到的输出是从小到大的。

另外如果用的是注释的那行代码,因为+返回值类型为引用型,上面已经有解释,所以会报错,错误如下:


最后在申明下,这个代码并不能对所有时间都适用,只因我当时做题需要才这么写的,应该也还是有参考价值的吧,希望能对读者有用。




  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值