其实是在做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 进行了排序,所以看到的输出是从小到大的。
另外如果用的是注释的那行代码,因为+返回值类型为引用型,上面已经有解释,所以会报错,错误如下:
最后在申明下,这个代码并不能对所有时间都适用,只因我当时做题需要才这么写的,应该也还是有参考价值的吧,希望能对读者有用。