C++运算符重载
系统的运算符需要符合特定的数据类型才可以使用,举个例子,默认情况下两个类对象p1,p2不能相加。我们可以通过运算符重载,使p1+p2可以相加,相加的结果则是由运算符重载函数的实现来定义。
运算符重载需要的关键字:operator
注:本文省略了为对象属性赋值的过程。
加号重载
创建一个类
class person
{
public:
int m_a;
int m_b;
};
想实现 p3.m_a=p1.m_a+p2.m_a; p3.m_b=p1.m_b+p2.m_b
这时可以使用运算符重载,使最终形式为p3=p1+p2。
有两种重载方式:
- 在成员函数中重载
- 在全局函数中重载
1.在成员函数实现重载。
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 p1;
person p2;
....
person p3=p1+p2;
2.在全局函数中实现
person operator+(person&p,person&b)
{
person temp;
temp.m_a=p.m_a+b.m_a;
temp.m_b=p.m_b+b.m_b;
return temp;
};
...
person p1;//注:这些操作在函数中写。
person p2;
...
person p3=p1+p2;
左移运算符重载
系统内置的类型,可以用<<简便地输出,而如果想输出一个对象的值,不能简单地用 <<对象,这时可以用左移运算符重载。
左移运算符重载不可以在成员函数中实现,只能在全局函数中实现
在全局函数中实现:
class person
{
public:
int m_a;
int m_b;
};
...
ostream& operator<<(ostream&cout,person&p)//步1
{
cout<<"p.m_a="<<p.m_a<<"p.m_b="<<p.m_b;//步2
return cout; //步3
}
//步1:左移运算符重载用到cout,cout属于ostream。用到person对象。两个都用引用。
//步2:这步中的cout是引用名cout,不是平时的cout。<<是平时的<<,还不是重载的<<。所以&cout可以换成&其他东西
//步3:返回cout,对应着函数类型ostream&,从可以不断的使用<< 例如:下面的在cout<<p1后面加上<<endl;
因为<<前面必须是ostream(即cout)
void teat01()
{
person p1;
p1.name="tom";
cout<<p1<<endl;//这步输出tom。
}
前置递增&后置递增运算符重载
递增运算符的重载用类内函数实现,不能用全局函数,递减同理。
class person
{
public:
person()
{
ma = 10;
mb = 20;
}
person& operator++()//前置递增
{
this->ma++;
this->mb++;
return *this;//this指向某一对象的地址,*this解引用,得到该对象,所以前面可以用person&接收。而且必须用引用的方式,否则如果遇上++++p1就行不通了,因为如果只是person而不是引用,则第一次++后返回的是一个拷贝的对象,不再是p1递增。
}
person& operator++(int)//后置递增,用int占位符,区别于前置递增
{
this->ma++;
this->mb++;
return *this;
}
int ma;
int mb;
};
ostream& operator<<(ostream& cout, person& p)
{
cout << p.ma <<" "<< p.mb;
return cout;
}
void test01()
{
person p1;
++p1;
cout << p1 << endl;
}
递减于递增同理。
赋值运算符重载
赋值运算符同样写在类内。
注:赋值运算符重载和拷贝构造函数一样,需要考虑堆区的问题。和深拷贝浅拷贝类似。
class person
{
public:
person()
{
ma = 10;
mb = 20;
m_age=new int(30);
}
person& operator=(person& p)//赋值运算符重载
{
ma = p.ma;
mb = p.mb;
if (m_age != NULL)//判断该指针是否为空,有则释放
{
delete m_age;
}
m_age = new int(*p.m_age);//然后这步和深拷贝方法类似。
return *this;//函数类型为person&以及返回类型为对象本身,这样可以使用类似p1=p2=p3的操作;
}
~person()
{
if (m_age != NULL)//有new就要注意析构函数中是否需要释放。
{
delete m_age;
m_age = NULL;
}
}
int ma;
int mb;
int* m_age;
};
void test01()
{
person p1;
//++p1
person p2;//步1
p2 = p1;//步2
cout << p1 << endl;
cout << p2 << endl;
}
注:上面的test01中,如果把步1步2换成
person p2=p1;
那么对于当前的程序来说会崩掉,因为这样运用的其实是拷贝构造函数,而不是赋值运算符重载函数。此时的拷贝函数是浅拷贝,所以会崩掉。