运算符重载概念:对已有得运算符重新进行定义,赋予其另一种功能,以适应不同得数据类型
加号运算符重载
#include <iostream>
#include <string>
using namespace std;
class Person
{
public:
int m_A;
int m_B;
//通过成员函数重载
Person operator+(Person &p)
{
Person temp;
temp.m_A = p.m_A + this->m_A;
temp.m_B = p.m_B + this->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& p1,int num)
{
Person temp;
temp.m_A = p1.m_A + num;
temp.m_B = p1.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 p1=p1.operater+(p2);
//全局函数重载本质调用
//Person p1=operator+(p1,p2);
Person p3 = p1 + p2;
//运算符重载也可以发生函数重载
Person p3 = p1 + 10;
}
int main()
{
void test01();
return 0;
}
左移运算符重载
利用成员函数重载
此时重载的左移运算符时得不到我们想要的形式
class Person
{
public:
int m_A;
int m_B;
//通过成员函数重载
void operator<<(ostream &p)
{
}
//此时重载后左移运算符的本质为:p.operator<<(cout),简化后为p<<cout 而非cout<<p
};
因此通常不会用成员函数重载左移运算符
用全局函数重载
/通过全局函数重载<<
void operator<<(ostream &out,Person &p2)
{
out << "m_A" << p2.m_A << "m_B" << p2.m_B;
}
但此时如果想在输出后加上<<endl
,换行,系统会报错。
这是因为函数返回的是void类型,改为
/通过全局函数重载<<
ostream &operator<<(ostream &out,Person &p2)
{
out << "m_A" << p2.m_A << "m_B" << p2.m_B;
return out;
}
后即可以追加,因此应有链式编程的思想。
此外用友元就可以让全局函数重载的左移运算符访问内部的私有变量。
递增运算符重载
重载前置++运算符
Person& operator++()
{
//先对变量进行++
m_Num++;//对变量进行++运算
//再返回变量++后的值,将自身作为一个返回
return *this;
}
注意一定要返回引用
当返回为值时
函数返回的是一个新的变量,即如果想对同一个数做多次++操作时,会出错。
因此要返回引用
返回引用是为了一直对一个数据进行递增操作
重载后置++运算符
用int区分前置后置++
如果直接写会因为重定义报错:
后置++时应:
1、 先记录当时结果
2、后递增
3、最后将记录结果返回
因此返回时不能用引用
赋值运算符重载
什么时候需要重载赋值运算符
正常情况下对类采用p1=p2
是可行的,但仅仅是值得拷贝:
class Person
{
public :
int *m_Age;
Person(int age)
{
m_Age=new int(age);//在堆区创建数据;
}
}
此时如果定义两个```Person``的类:
Person p1(18);
Person p2(20);
//将p1的值赋值给p2
p2=p1;
//此时系统是不会报错的
但如果我们写了析构函数将堆区创建的数据释放掉:
~Person()
{
if(m_Age!=NULL)
{
delete m_Age;
m_Age=NULL;
}
}
此时系统会报错,这是因为在赋值时仅仅是值的拷贝,这样会时得堆区得数据重复释放.
因此此时需要深拷贝
Person& operator=(Person& p)
{
//编译器提供得是浅拷贝
//m_Age=p.m_Age
//注意应该先判断是否有属性在堆区,如果过有先释放干净,再深拷贝;
if (m_Age != NULL)
{
delete m_Age;
m_Age = NULL;
}
//深拷贝
m_Age = new int(*p.m_Age);
return *this;
}
注意此时要返回引用:
1、应有链式编程得思想,可以实现连等
2、如果返回得是值,那么就是在调用拷贝构造函数再创建一个类,而并非本事。
关系预算符重载
函数调用运算符重载