3、运算符重载
约 1710 字大约 6 分钟
2025-06-22
概念
对已有的运算符重新进行定义,赋予另一种功能,以适用不同的数据类型
运算符重载分为两类,一个是成员函数重载运算符,一个是全局函数重载运算符 两种运算符重载不能同时存在
加号运算符重载
class Person{
public:
int m_a;
int m_b;
//成员函数重载+运算符
// Person operator+(Person &p){
// Person temp;
// temp.m_a= this->m_a+p.m_a;
// temp.m_b= this->m_b+p.m_b;
// return temp;
// }
};
//全局函数重载+运算符
Person operator+(Person &p1,Person &p2){
Person temp;
temp.m_a=p1.m_a+p2.m_a;
temp.m_b=p1.m_b+p2.m_b;
return temp;
}
//运算符重载构成函数重载
Person operator+(Person &p,int num){
Person temp;
temp.m_a=p.m_a+num;
temp.m_b=p.m_b+num;
return temp;
}
int main(){
Person p1;
p1.m_a=10;
p1.m_b=10;
Person p2;
p2.m_a=10;
p2.m_b=10;
//Person p3=p1.operator+(p2);//成员函数重载的本质
//Person p3= operator+(p1,p2);//全局函数重载的本质
//重载运算符简化运用
Person p3=p1+p2;//不定义运算符重载(Person operator+)会报错,因为编译器不知道这个加号怎怎么操作
Person p4=p1+100;
cout<<p3.m_a<<"\t"<<p3.m_b<<endl;
cout<<p4.m_a<<"\t"<<p4.m_b<<endl;
return 0;
}运算符重载也能发生函数重载
左移运算符重载
利用成员函数重载左移运算符
p.operator<<(cout)简化版本为p<< cout cout在右边,所以一般不会利用成员函数重载左移运算符,因为无法实现cout在左边
cout在iostream头文件里定义是属于ostream类的因此重载左移运算符时带数据类型传入cout时应为ostream cout
class Person{
public:
int m_a;
int m_b;
};
//利用全局函数重载左移运算符
ostream & operator<<(ostream &cout,Person &p){//本质cout<<p
cout <<p.m_a<<"\t"<<p.m_b;
return cout;
}
int main(){
Person p;
p.m_a=10;
p.m_b=10;
cout<<p<<endl;
return 0;
}在不知道返回类型时可以先写void,但此时使用左移运算符重载不能在后边输入endl
ostream & operator<<(ostream &cout,Person &p){//本质cout<<p
cout <<p.m_a<<"\t"<<p.m_b;
return cout;
}加入endl后第二个<<后不为Person类型,所以使用iostream中定义的<< 此处是一个函数重载,执行完第一个<<之后语句为cout<< endl
递增运算符重载
成员函数重置递增运算符返回值返回引用,如果不返回引用直接返回值也正确,但返回引用不会调用拷贝构造函数
class Myinter{
public:
int num;
Myinter(){
num=0;
}
//重置前置递增运算符
//返回引用是为了对一个数据进行递增操作,如果不返回引用返回的是一个新的值
Myinter & operator++(){
++num;
//自身返回
return *this;
}
//重置后置递增运算符
//加int占位参数这样就能和前置递增重置构成函数重载,用以区分前置和后置
//返回 值,因为temp是一个局部变量,不能返回引用
Myinter operator++(int){
//先记录当前结果
Myinter temp=*this;
//后递增
num++;
return temp;
}
};
//利用全局函数重载左移运算符
//用于输出前置递增运算符重载
ostream & operator<<(ostream &cout,Myinter &p){//本质cout<<p
cout <<p.num;
return cout;
}
//利用全局函数重载左移运算符
//用于数据后置递增运算符重载,虽然构成函数重载但不能和前置的同时存在,同时存在时使用重载后的前置运算符会不知道该调用哪个函数而报错
ostream & operator<<(ostream &cout,Myinter p){//本质cout<<p
cout <<p.num;
return cout;
}
int main(){
Myinter myinte;
//cout<<++(++myinte)<<endl;//2
//cout<<myinte<<endl;//重置递增运算符如果返回引用会是正常的2,如果返回值 会是1,因为第一次递增返回的是一个新值不会进行第二次递增操作
cout<<myinte++<<endl;
cout<<myinte++<<endl;
return 0;
}前置运算符重载返回引用,后置运算符重载返回值
递减运算符重载
和递增运算符重载类似
赋值运算符重载
C++编译器至少给一个类添加5个函数 1.默认构造函数(无参,函数体为空) 2.默认析构函数(无参,函数体为空) 3.默认拷贝构造函数,对属性进行值拷贝 4.赋值运算符operator=,对属性进行值拷贝 5.移动构造,移动赋值 如果类中有属性指向堆区,做赋值操作时也会出现深浅拷贝问题 浅拷贝只拷贝,深拷贝在堆区开辟内存进行拷贝
解决浅拷贝问题
赋值运算符的运算顺序时从右往左(向左赋值)
class Person{
public:
int *m_age;
Person(int age){
m_age=new int(age);
}
~Person(){
if(m_age!=NULL){
delete m_age;
m_age=NULL;
}
}
Person & operator=(Person &p){
//先判断是否有属性在堆区,如果有先释放然后再深拷贝
if (m_age!=NULL){
delete m_age;
m_age=NULL;
}
//深拷贝
m_age=new int(*p.m_age);
//浅拷贝
//p1.m_age=p2.m_age;
//返回自身为了能让连续使用如p3=p2=p1
return *this;
}
};
int main(){
Person p1(18);
Person p2(20);
Person p3(30);
p2=p1;
cout<<*p1.m_age<<endl;
cout<<*p2.m_age<<endl;
cout<<"-------------------"<<endl;
int a=10;
int b=20;
int c=30;
c=b=a;
cout<<"a="<<a<<endl;
cout<<"b="<<b<<endl;
cout<<"c="<<c<<endl;
cout<<"-------------------"<<endl;
p3=p2=p1;
cout<<*p1.m_age<<endl;
cout<<*p2.m_age<<endl;
cout<<*p3.m_age<<endl;
return 0;
}关系运算符重载
class Person{
public:
Person(string name,int age){
m_name=name;
m_age=age;
}
string m_name;
int m_age;
bool operator==(Person &p){
if (m_name==p.m_name && m_age==p.m_age){
return true;
}
else{
return false;
}
}
};
int main(){
Person p1("tom",18);
Person p2("jerry",18);
if (p1==p2){
cout<<"=="<<endl;
}
else{
cout<<"!="<<endl;
}
return 0;
}其他关系运算符类似
函数调用运算符重载
函数调用运算符() 也可以重载由于重载后使用的方式非常像函数的调用,因此称为仿函数 仿函数没有固定写法,非常灵活,其对象称为函数对象
函数对象(仿函数)是一个类,不是一个函数 分类:如果冲在最的operator()要求获取一个参数,这个类就被称为一元仿函数,如果要求获取两个参数就被称为二元仿函数
//实现字符型和整形相乘
class Mymultiplication{
public:
void operator()(string str,int num){
for (int i = 0; i < num; i++) {
cout<<str;
}
}
};
int main(){
Mymultiplication mymultiplication;
mymultiplication("hello world ",10);
//匿名函数对象,与上面实例化一个类后再调用重载函数调用运算符效果一样
Mymultiplication()("hello world ",10);
return 0;
}谓词
返回bool类型的仿函数被称为谓词 如果operator接收一个参数就叫一元谓词 如果operator接收两个参数就叫二元谓词
匿名函数
语法:类名()(参数列表) 匿名函数当前行执行完立即被释放
类型操作符重载
operator int()不用写返回类型 operator加类型 的重载方式是将此类型转化成指定类型。
贡献者
版权所有
版权归属:wynnsimon
