运算符重载
作用:用户自己编写运算符功能,两个类之间直接用普通运算符不行,那就重载运算符
用法:将 成员函数/全局函数 名起为 operator<符号>
加号运算符重载
#include <iostream>
using namespace std;
class person {
public:
int num;
};
person operator+ (const person &p1,const person &p2) {
person* temp = new person;
temp->num = p1.num + p2.num;
return *temp;
}
void main() {
person p1;
p1.num = 10;
person p2;
p2.num = 13;
person p3 = p1 + p2;//本质上p3=operator+(p1,p2)
cout<<p3.num<<endl;
}
注意:运算重载的函数也能重载
左移运算符重载
#include <iostream>
using namespace std;
class person {
public:
int num;
};
//返回值为ostream& cout,能够进行链式编程
ostream& operator<<(ostream &cout, const person& p) {//重载了<<,简化可写cout<<p
cout << p.num << endl;
return cout;
}
void main() {
person p1;
p1.num = 10;
cout<<p1;//如果不写返回值为ostream& cout就只能这样写
cout<<p1<<endl;//如果不写返回值为ostream& cout这样写会报错
}
递增运算符重载
#include <iostream>
using namespace std;
class person {
friend ostream& operator<<(ostream& cout, const person& p);
private:
int num;
public:
person(int num):num(num) {}
//前置
person& operator++() {
num++;
return *this;
}
//后置
person operator++(int) {//加入了占位参数之后,就变成后置递增了
person temp = *this;//返回一个当前值,没有自加的
num++;//但是本事这个类实例是已经递增的了
return temp;//通过这种手法实现了后置递增
}
};
ostream& operator<<(ostream &cout, const person& p) {
cout << p.num << endl;
return cout;
}
void main() {
person p1(10);
cout<<++p1<<endl;
cout<<p1++<<endl;
cout << p1 << endl;
}
赋值运算符重载
有问题的操作,析构函数重复释放堆区内存
#include <iostream>
using namespace std;
class person {
friend ostream& operator<<(ostream& cout, const person& p);
private:
int *num;
public:
person(int num){
this->num = new int(num);
}
~person() {
if (this->num != NULL)
delete(this->num);
}
};
ostream& operator<<(ostream &cout, const person& p) {
cout << *p.num;
return cout;
}
void main() {
person p1(10);
person p2(12); /*这样会报错,因为析构的时候会重复释放this->num指向的内存空间*/
/*系统默认的拷贝函数是浅拷贝,更改的只是指针的指向,所以两个类*/
p2=p1; /*的num指针指向同一块内存 */
cout << p1 << endl;
cout << p2 << endl;
}
重载后
#include <iostream>
using namespace std;
class person {
friend ostream& operator<<(ostream& cout, const person& p);
private:
int *num;
public:
person(int num){
this->num = new int(num);
}
~person() {
if (this->num != NULL)
delete(this->num);
}
//赋值符号重载操作,返回值使得其能够进行链式操作,p3=p2=p1
person& operator=(person &p) {
if (num != NULL) {
delete num;
num = NULL;
}
num = new int(*p.num);
return *this;
}
};
ostream& operator<<(ostream &cout, const person& p) {
cout << *p.num;
return cout;
}
void main() {
person p1(10);
person p2(12);
p2=p1;//因为等于号已经重载了,所以析构的时候不会出现内粗你重复释放的问题
cout << p1 << endl;
cout << p2 << endl;
}
关系运算符重载
#include <iostream>
using namespace std;
class person {
friend ostream& operator<<(ostream& cout, const person& p);
private:
int *num;
public:
person(int num){
this->num = new int(num);
}
~person() {
if (this->num != NULL)
delete(this->num);
}
//关系运算符重载
bool operator==(person &p) {
if(*this->num == *p.num)
return true;
return false;
}
};
ostream& operator<<(ostream &cout, const person& p) {
cout << *p.num;
return cout;
}
void main() {
person p1(10);
person p2(12);
if (p2 == p1)//前面不写==运算符则这里会报错
cout<<"p2等于p1"<<endl;
else
cout << "p2不等于p1" << endl;
}
函数调用运算符重载
函数调用运算符()也可以重载
由于重载后的使用方式和函数非常相似所以成为仿函数
#include <iostream>
#include <string>
using namespace std;
class person {
public:
void operator()(string test) {//函数调用运算符重载
cout << test << endl;
}
};
void main() {
person p;
p("hello world");//等价于p.operator()("hello world")
}
也可以进行匿名类的调用
函数调用运算符重载
函数调用运算符()也可以重载
由于重载后的使用方式和函数非常相似所以成为仿函数
#include <iostream>
#include <string>
using namespace std;
class person {
public:
void operator()(string test) {//函数调用运算符重载
cout << test << endl;
}
};
void main() {
person()("hello world");//这样就无需创建一个实例,用完系统立即回收
}
总结:运算符重载的用处非常多,而且也便于阅读和编程,是一个很实用的技能。
注意:编程的时候要做好注释,否则容易出现忘记重载的参数是什么的问题