结构体运算符的简单重载
在算法竞赛中我们经常会使用结构体来保存我们需要的变量,但在我们需要进行排序或使用一些需要运算符的STL容器时,我们往往会定义一个函数cmp来保存,但这不是一个万全的方法.
假如现在需要保存每个人的名字,身高,年龄等信息
我们很容易想到要用结构体 来进行保存
const int maxn=1e6;
struct people{
std::string name;
unsigned int age;
unsigned int height;
}pp[maxn];
设我们现在需要按照name来进行排序
一般我们会在外面定义一个cmp函数
bool cmp(people x,people y)
{
return x.name<y.name;
}
再使用sort来排序
sort(pp,pp+n,cmp);
当然这样做确实是好的,但在很多情况下重载运算符更好.
关键字 operator
运算符的重载和函数很像
这里我们先看operator的一个使用
const int maxn=1e6
struct people{
std::string name;
unsigned int age;
unsigned int height;
bool operator<(const people & t)
{
return name<t.name;
}//按照名字的字典序来排序
}pp[maxn];
看到这里,大家可能就会问了:为什么函数里面前面的是name,后面是t.name.
因为我们是在结构体里的直接重载的,所以可以直接调用结构体里的变量,后面的t则需要使用"."运算符;
若我们把重载运算符看作函数,则
//bool operator<(const people & t);
//是一个返回值为bool 型的 接受一个参数 const people & 的函数
people a,b;
a.name="Jane";a.age=12;a.height=165;
b.name="Tom";b.age=13;b.height=170;
if(a<b)cout<<a.name;//这里 可以看作成调用了a的成员函数
// a<b == a.operator<(b)
else cout<<b.name;
当进行a<b比较时,相当于调用了a的成员函数.
以此类推,我们可以写出这个结构体的其他运算符
注:如果像这样重载运算符,在使用sort时,有些编译器会出现玄学错误,后面会讲适合sort的方法
bool operator >(const people & t)
{
return t<*this;//this 指针
//可以调用已经有了的运算符
}
bool operator ==(const people & t)
{
return this->name==t.name;//this->name ==name;
}
//其他>= ,<=, !=运算符省略...
this 指针
this指针是运用于结构体和类对象(可以不管)中的一个指针,它指向的是当前这个结构体(类)本身,由于是指针,所以使用时要调用某个变量则可以用->来表示 例如上面的实例.*this则是表示这个结构体,this指针可以解决一些需要调用本身的尴尬问题等等.
上面的this->name也就是结构体的name;可以很好的区分.
重载输入输出运算符 >> ,<<
现在我们遇到了一个尴尬的问题----我们在对结构体重载运算符时只能选择结构体作为前一个参数,另一个变量做后面的参数.
如果我们在结构体里定义形如 bool operator >(const string & t,const people & peo);的形式;则会报错;
同时,上面提到只在结构体里重载该结构体的后面一个参数的话sort也会出现玄学错误.
这种情况有两种解决方法
- 在结构体外面重载运算符,可以添加两个参数.
- 在结构体内重载运算符,在前面添加friend关键字,添加两个参数.
第一个就直接定义两个参数的就行
//结构体外~
bool operator (const string & name,const people & t)//可以添加想要比较的对象的先后顺序
{
return name<t.name;
}
bool operator (const people & t,const string & name)
{
return t.name<name;
}
void operator = (const string & k,const people & t)//重载赋值运算符
{
k=t.name;
return;
}
第二种方法则是在结构体内加friend
//结构体内~
friend bool operator <(const people & a,const people & b)
{
//如果像这样重载<运算符则sort不会有玄学错误
//可以定义在外,外面请不要加friend
//格式如此,friend加在最前面
return a.name<b.name;
}
那么我们现在就可以重载输入输出运算符啦~
//为了加深印象 前面重载在内,重载在外各一个
//内
friend ostream & operator<<(ostream & os,const people & t)
{
//由于ofstream 是由ostream派生来的,所以可以不管
//oier听不懂没关系,无视不影响
//记住一定要返回ostream & !!!,第一个参数也要&!!!,不然无法连用
os<<t.name<<' '<<t.age<<' '<<t.height;
return os;
}
//外
istream & operaotr>>(istream & is,const people & t)
{
is>>t.name>>t.age>>t.height;//顺序皆为名字,年龄,身高
return is;
}
ps : 用多了就会感觉只是函数换了个名字...
----------------------------------------2018 9,9 更新-------------------------------------------------
最近同学问我怎么重载+ - * /,其实方法都一样的;这里就举一个例子:
//矩阵乘法
struct Matrix{
enum array_size{maxn=1005};
long long a[maxn][maxn];
friend Matrix operator * (const Matrix & x,const Matrix & y)
{
Matrix t;
for(int i=1;i<=1000;i++)
for(int j=1;j<=1000;j++)
for(int k=1;k<=1000;k++)
t.a[i][j]+=x.a[i][k]*y.a[k][j];
return t;
}
};
如有错误或疑问请留言给我O(∩_∩)O