c++运算符重载使用说明

运算符重载概念:

对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型

一般有+,左移,递增,赋值,关系函数调用这几种运算符重载

基本形式为

返回类型 operator @ (参数表)

 
(1)+运算符重载

person+int类型

```cpp
Person operator+(Person &p,int num)
{
 Person temp;
 temp.m_A=p.m_A+num;
 temp.m_B=p.m_B+num;
 return temp;
}

全局函数Person operator+(Person &p1,Person &p2)

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+person类型

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;
 }

下面是实例

#include<iostream>
using namespace std;
class Person
{
public:
 //成员函数重载+号 ,成员函数重载本质是Person p3=p1.operator+(p2) 
 /*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;
 }*/
 int m_A;
 int m_B;
};
//全局函数重载本质是Person p3=operator(p1+p2) 
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;
}
void test01()
{
 Person p1;
 p1.m_A=10;
 p1.m_B=10;
 Person p2;
 p2.m_A=10;
 p2.m_B=10;
 Person p3=p1+p2;
 Person p4=p3+100;//运算符重载也可以发生函数重载,person+int类型 
 cout<<"p3.m_A="<<p3.m_A<<endl;
 cout<<"p3.m_B="<<p3.m_B<<endl;
 cout<<"p4.m_A="<<p4.m_A<<endl;
 cout<<"p4.m_B="<<p4.m_B<<endl;
}
int main()
{
 test01();
}

运行结果如图
在这里插入图片描述

(2)左移运算符重载

左移运算符重载有几点需要注意

cout<<p1<<"hello world"<<endl;

这是一个链式编程,输出p1之后需要返回值为cout类型,而cout的类型是ostream,所以需要使用 ostream& 进行重载

#include<iostream>
using namespace std;
class Person
{
 friend ostream& operator<<(ostream& out,Person& p);
public:
 Person(int a,int b)
 {
  this->m_A=a;
  this->m_B=b;
 }
private:
 int m_A;
 int m_B;
};
ostream& operator<<(ostream& out,Person& p )
{
 out<<"a:"<<p.m_A<<" b:"<<p.m_B<<endl;
 return out;
}
void test01()
{
 Person p1(10,20);
 cout<<p1<<"hello world"<<endl;
}
int main()
{
 test01();
}

运行结果是
在这里插入图片描述

(3)递增运算符重载

前置++和后置++的区别

int a=10;
cout<<++a<<endl;//11
cout<<a<<endl;//11

int b=10;
cout<<b++<<endl;//10
cout<<b<<endl;//11

前置运算符返回的是指针,后置运算符返回的是数值,二者靠int区别

想输出类cout<<++myInt<<endl;还要用到左移运算符重载,全局函数声明

#include<iostream>
using namespace std;
class MyInteger
{
	friend ostream& operator<<(ostream& out,MyInteger myint);
public:
    MyInteger()
	{
		num=0;
	}	
	//前置递增运算符++也写后面,靠(int)与后置区分 
	MyInteger& operator++()
	{
		num++;
		return *this;
	}
	MyInteger operator++(int)
	{
		//保存
		MyInteger temp=*this;
		//进行++
		num++;
		// 返回保存的 
		return temp;
	}
private:
		int num;
};
ostream& operator<<(ostream& out,MyInteger myint)
{
	out<<myint.num;
	return out;
}
void test01()
{
	MyInteger myInt;
	cout<<++myInt<<endl;
	cout<<myInt<<endl;
}
void test02()
{
	MyInteger myInt;
	cout<<myInt++<<endl;
	cout<<myInt<<endl;
}
int main()
{
	test01();
	test02();
}

运行结果是
在这里插入图片描述

(4)赋值运算符重载

C++编译器至少给一个类添加4个函数

1.默认构造函数(无参,函数体为空)

2.默认析构函数(无参,函数体为空)

3.默认拷贝构造函数,对属性进行值拷贝

4.赋值运算符operator=,对属性进行值拷贝

如果类中有属性指向堆区,做赋值操作时也会出现深浅拷贝问题

浅拷贝会带来堆区内存重复释放的问题,造成系统崩溃,这个问题就要用深拷贝解决,即开辟一块新的内存

对深浅拷贝不太了解的,可以看一下我之前写的文章深浅拷贝

下面是例子

#include<iostream>
using namespace std;
class Person
{
public: 
	Person(int age)
    {
    	m_Age=new int(age);
	}
	//赋值运算符重载
	//编译器提供的是浅拷贝,m_Age=p. m_Age
	Person& operator=(Person &p)
	{
		if(m_Age!=NULL)//要先判断堆区内存是否释放干净 
		{
			delete m_Age;
			m_Age=NULL;
		}
		m_Age=new int(*p.m_Age);//开辟一块新内存
		return *this;//返回本身,满足链式结构 
	}
	~Person()//析构函数释放堆区内存 
	{
		if(m_Age!=NULL)
		{
			delete m_Age;
			m_Age=NULL;
		}
		
	}
	int* m_Age;
};
void test01()
{
	Person p1(18);
	Person p2(20);
	Person p3(30);
	p3=p2=p1;
	cout<<"p1的年龄为:"<<*p1.m_Age<<endl;
	cout<<"p2的年龄为:"<<*p2.m_Age<<endl;
	cout<<"p3的年龄为:"<<*p3.m_Age<<endl;
}
int main()
{
	test01();
}

运行结果如下
在这里插入图片描述
(5)关系运算符重载

关系运算符: <, > , ==, !=

#include<iostream>
using namespace std;
class Person
{
public: 
	Person(string name,int age)
	{
		m_Name=name;
		m_Age=age;
	}
	bool operator==(Person p)
	{
		if(this->m_Age==p.m_Age&&this->m_Name==p.m_Name)
		{
			return true;
		}
		else
		{
			return false;
		}
	}
	bool operator!=(Person p)
	{
		if(this->m_Age==p.m_Age&&this->m_Name==p.m_Name)
		{
			return false;
		}
		else
		{
			return true;
		}
	}
	string m_Name;
	int m_Age;
};
void test01()
{
	Person p1("Tom",18);
	Person p2("Tom",18);
	if(p1==p2)
	{
		cout<<"p1和p2是相等的"<<endl;
	}
	else
	{
		cout<<"p1和p2是不相等的"<<endl;
	}
	if(p1!=p2)
	{
		cout<<"p1和p2是不相等的"<<endl;
	}
	else
	{
		cout<<"p1和p2是相等的"<<endl;
	}
}
int main()
{
	test01();
}

运行结果如下
在这里插入图片描述

(6)函数调用运算符重载()

·函数调用运算符()也可以重载

·由于重载后使用的方式非常像函数的调用,因此称为仿函数

·仿函数没有固定写法,非常灵活

#include<iostream>
using namespace std;
class MyPrint
{
public: 
	MyPrint(string name)
	{
		cout<<name<<endl;
	}
};
void test01()
{
	MyPrint p1("Tom");
}
class MyAdd
{
public:
    int operator()(int a,int b)
	{
		return a+b;
	}	
};
void test02()
{
	MyAdd add;
	int ret=add(1,2);
	cout<<"ret="<<ret<<endl;
	cout<<MyAdd()(1,2)<<endl;//匿名对象调用 
}
int main()
{
	test01();
	test02();
}

运行结果如下

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_45721778/article/details/105786750
今日推荐