结构体的运算符重载
C++中,结构体是无法进行==,>,<,>=,<=,!=操作的,如要使用这些操作符对结构体进行操作,则可以在结构体内部对这些运算符进行重载,将结构体的比较转化为结构体内部的数字或者字符的比较。
方式一:结构体内部的重载
return(什么时候这个运算符对结构体成立);
priority_queue<tmp>q;//优先队列
方式二:结构体外的重载
priority_queue<tmp,vector<tmp>,cmp>q;;//优先队列
来源1:https://blog.csdn.net/sunny1996/article/details/51242184
来源2:简书
来源3:https://www.cnblogs.com/MekakuCityActor/p/8455379.html
关于结构体运算符重载解释的比较清楚的文章:http://www.cppblog.com/sixleaves/archive/2014/08/29/208178.aspx
第一:运算符重载的基本应用。第二:运算符重载于友原函数的关系。第三:结构体于类关于运算符重载的区别。首先我需要普及下基本的知识:
预备知识:operator(操作符)、operand(操作数)、表达式
表达式是由操作符和操作数构成的,而且一般每个表达式都有副作用,并且都有结果(关注结果和副作用)。什么意思?
关于副作用的理解:其实就是在达到结果的这个过程中所做的一些事情,而这些事情产生了一些影响,但是不影响结果。
好像有点绕、看看例子在理解吧。
看例子:
int a = 1,b=2,c; c = a + b;
在这段代码里面,c = a + b;就是表达式、其中 = 、 + 又称为操作符、c、a、b又称为操作数。其结果就是计算出了a+b的值,副作用没有。
又比如:
cout << "Helloe" << endl;其中 <<是操作符、cout、"helloe"、endl是操作数。<<的结果是返回了ostream的引用,而副作用就是将"Helloe"输出到屏幕。
第一:运算符重载的基本应用。
看如下代码:
2
3 using namespace std;
4
5 class Point {
6 private:
7 double x,y;
8 public:
9 Point(double x = 0, double y = 0):x(x),y(y) {
10
11 }
12 Point operator+(const Point &p) const{//这种是最基本的方式、其本质是做操作数调用operator+函数
13 Point temp;
14 temp.x = this->x + p.x;
15 temp.y = this->y + p.y;
16 return temp;
17 }
18 /*
19 ostream& operator<<(ostream& out) {
20 out << x << " " << y;
21 return out;
22 }
23 */
24 friend ostream& operator<<(ostream& out, Point & p);
25 };
26 ///*
27 ostream& operator<<(ostream& out, Point & p) {
28 out << p.x <<" "<< p.y;
29 return out;
30 }
31 //*/
32
33 int main() {
34
35 Point a(1,5);
36 Point b(5,7);
37 Point c;
38 c = a + b;
39 //c << cout << endl;
40 cout << c << endl;
41 return 0;
42 }
如上代码:
注释掉的先不用看,12--17行就是最基本的运算符重载、其调用在38行,本质是:c = a.operator+(b);也就是调用做操作数的方法那么还要友元函数干什么呢?考虑下输出,如果你想让cout对象能自动输出Point的对象如何半到。你很聪明一定想到重载<<运算符、yes!right!于是把operator<<作为成员函数,你只能写成上面注释掉的哪样,那么调用时,麻烦就来了、编程39行的样子。尼玛丫、真实变态、我是想让它是cout << c << endl。搞得四不像了。是的就是因为这样子不好用,所以我们要结合友元函数的技术和运算重载技术来实现40行的调用。好了重点来了!谨记之!
tips:对于非成员函数的运算符重载,第一个参数就是左操作数,第二个操作数就是右操作数。
第二:运算符重载和友原函数的关系
所以上面的友元函数的参数顺序是cout对象的引用是第一个参数、Point对象引用为第二个参数。
我们还要解决第二个问题,如何让这个函数访问Point对象的私有部分,只要在Point类中声明,hello我是你的朋友啦、他的东西就是你的啦、你要怎么用怎么用,这才是朋友么!不、是基友!我认为应该叫做基友函数,哈哈。声明格式就是加上friend和函数的声明即可。
tips:成员函数和非成员函数的运算符重载的区别就是,参数个数不一样。成员函数中的左操作数不用体现出来(用this即可)、而非成员函数的左右操作数都要体现在运算符函数参数里面。
第三:结构体和类关于运算符重载的区别
关于区别,其实只有一个,因为结构体默认的权限是public、即其成员对外界都是可见的,所以其不需要友元函数来支持,但是其还是需要用非成员函数来重载<<比较方便、而不是用成员函数来重载<<.原因上面已经说过了。注意这个原因不是友元这项技术体现出来的,而是成员函数和非成员函数体现出来的,友元技术知识用来支撑其在类中的应用。、
tips:对于结构体,非成员函数的运算符重载方法,不需要声明为友元函数。
如下代码:
2
3 using namespace std;
4
5 struct Point{
6 double x,y;
7 Point(double x = 0, double y = 0):x(x),y(y) {
8
9 }
10 Point operator+(const Point &p) const{//这种是最基本的方式、其本质是做操作数调用operator+函数
11 Point temp;
12 temp.x = this->x + p.x;
13 temp.y = this->y + p.y;
14 return temp;
15 }
16 };
17
18 ostream& operator<<(ostream& out, Point & p) {
19 out << p.x <<" "<< p.y;
20 return out;
21 }
22
23
24 int main() {
25
26 Point a(1,5);
27 Point b(5,7);
28 Point c;
29 c = a + b;
30 cout << c << endl;
31 return 0;
32 }