运算符重载概念
1. // 运算符重载是C++强大的特性之一,运算符重载有以下几种限制
// 不可臆造新的运算符
// 不能改变运算符原有的优先级、结合性和语法结构,不能改变操作数个数
// 运算符重载不家使用过多
// 运算符重载含义必须清楚,不能有二义性
// 必须遵循函数重载的规则
// 必要时可借用码元函数来完成运算符重载
// .和.* :: sizeof ?:: 均不可重载。可理解为带点的运算符都不可重载
// 重载的运算符对象必须要有自定义的类型,否则会与原来的系统冲突
// 操作系统已经为每一个新声明的类重载了一个赋值运算符和取址运算符
// 不建议重载&&和||,因为重载后它们失去了短路现象,会导致逻辑错误
运算符重载的方式
- 成员函数重载
- 不需要借助friend
- 类对象本身已经变成该运算符的左参数,即this
=,[],(),->
,这4个运算符只能用成员函数重载
- 全局函数
- 左移运算符:
friend ostream& operator(ostream& out,const Time& t)
- 它的左操作数为ostream,是一个无法修改的内置类,所以只能用全局函数重载
重载<<运算符
// 声明为友元函数,调用:cout << c << endl;
friend ostream& operator<<(ostream& os, Complex& c);
ostream& operator<<(ostream& os, Complex& c)
{
os << "(" << c.a << "," << c.b << "i)";
return os;
}
ostream& operator<<(ostream& os, myInt myint)
{
os << myint.m_Num;
return os;
}
// 声明为成员函数,调用方式为:c << cout << endl;
ostream& operator<<(ostream& out)
{
out << "(" << real << ", " << img << ")" << endl;
return out;
}
重载赋值运算符
class Person
{
public:
int* m_age;
Person():m_age(NULL){}
Person(int age){m_age = new int(age);}
Person& operator=(Person& p)// 在调用时,Person p2=p1;将p1的拷贝到p2
{ // 应先判断是否有属性在堆区,如果有,先释放,再深拷贝
if (this->m_age!=NULL){delete this->m_age;this->m_age = NULL;}
this->m_age = new int(*p.m_age);
return *this;
}
~Person(){if (m_age!=NULL){ delete m_age; m_age = NULL; } }
};
// 赋值运算符重载需要深拷贝的原因
// 因为有在堆上开辟空间,故需自定义析构函数,释放堆上空间
// 调用赋值运算符时:Person p2=p1; // 结束一先析构p2再析构p1
// 析构p2时,已经释放一次堆上空间,析构p1双释放一次,报错,需深拷贝