运算符重载
学习目的:
掌握运算符重载规则 能够自主实现运算符重载
通过重载运算符,扩展运算符功能
内容:
基础语法(**) 规则详细了解
重载 >> 和 << 注意事项(**)
基础语法
重载的概念:重新赋予含义或内容。
运算符重载实质上就是定义一个新的函数,去赋予运算符一个新的功能或规则。
#include <iostream>
using namespace std;
class MyComplex
{
public:
MyComplex(double real = 0.0, double imag = 0.0);
~MyComplex();
void display() const;
// 返回值类型 函数名(形参列表){}
// 函数名:operator运算符名称
/*MyComplex operator+(MyComplex other)
{
MyComplex obj;
obj.m_real = this->m_real + other.m_real;
obj.m_imag = this->m_imag + other.m_imag;
return obj;
}*/
const MyComplex & operator+(const MyComplex& other) const ;
private:
double m_real;
double m_imag;
};
MyComplex::MyComplex(double real, double imag)
: m_real(real), m_imag(imag)
{
}
void MyComplex::display() const
{
cout << "(" << m_real << '+' << m_imag << 'i' << ')' << endl;
}
// 如果去掉 返回值中的 const 则会报: 非常量引用的初始值必须为一左值;
// 表面: 函数体中 return 后面的表达式是一个常量(参数传进来的时候就是常量)。
const MyComplex& MyComplex::operator+(const MyComplex& other) const
{
// 创建了一个没有名字的临时对象(代码报错,修改为下列代码)
return MyComplex(this->m_real + other.m_real, this->m_imag + other.m_imag);
/*MyComplex obj;
obj = MyComplex(this->m_real + other.m_real, this->m_imag + other.m_imag);
return obj;*/
}
// 注:使用引用的好处是避免多次调用拷贝构造函数
MyComplex::~MyComplex()
{
}
int main()
{
MyComplex obj_1(3, 5);
obj_1.display();
MyComplex obj_2(4, 6);
obj_2.display();
MyComplex obj_3;
obj_3 = obj_1 + obj_2;
obj_3.display();
// obj_1 + obj_2;
return 0;
}
注:1. 返回值为引用类型时,暂未完全搞明内部逻辑(引用可理解为一个常量指向的指针,当作变量去用。);
2. 拷贝构造函数的理解还需进一步学习;
3. 创建一个无名临时对象能否被引用变量接收??(MyComplex & MyComplex::operator+(const MyComplex& other) const 函数体中注释部分报错。)(注释中已针对该问题进行修改,错误排除。——>paper tiger !)
全局函数示例:
#include <iostream>
using namespace std;
class MyComplex
{
public:
MyComplex(double real = 0.0, double imag = 0.0);
~MyComplex();
void display() const;
// 声明为友元函数
friend MyComplex & operator+(const MyComplex & obj1, const MyComplex & obj2);
private:
double m_real;
double m_imag;
};
// 定义为全局函数,对于 私有成员 的使用需声明为该类的友元函数
MyComplex & operator+(const MyComplex & obj1, const MyComplex & obj2);
int main()
{
MyComplex obj_1(3, 5);
obj_1.display();
MyComplex obj_2(4, 6);
obj_2.display();
MyComplex obj_3;
obj_3 = obj_1 + obj_2;
obj_3.display();
// obj_1 + obj_2;
return 0;
}
MyComplex & operator+(const MyComplex & obj1, const MyComplex & obj2)
{
MyComplex obj;
obj = MyComplex(obj1.m_real + obj2.m_real, obj1.m_imag + obj2.m_imag);
return obj;
}
/** MyComplex **/
MyComplex::MyComplex(double real, double imag)
: m_real(real), m_imag(imag)
{
}
void MyComplex::display() const
{
cout << "(" << m_real << '+' << m_imag << 'i' << ')' << endl;
}
MyComplex::~MyComplex()
{
}
运算符重载规则
并不是所有运算符都可以重载;
重载不能改变运算符的优先级和结合性;
重载不会改变运算符的用法(单目运算符仍然为单目运算符);
运算符重载不能有默认的参数;
运算符重载函数可以作为类的成员函数也可以作为全局函数(作为成员函数时使用参数个数应比目数少一,使用类中的this指针)。
箭头运算符 -> 下标运算符 [] 赋值运算符 = 函数调用运算符 () 只能以成员函数的形式重载。
重载 >> 和 <<
- 建议作为友元函数重载(避免使用this指针和修改内部库函数文件)
- 示例:
#include <iostream>
using namespace std;
class MyComplex
{
public:
MyComplex(double real = 0.0, double imag = 0.0);
friend istream & operator>>(istream & in, MyComplex & com);
friend ostream & operator<<(ostream & out, const MyComplex & com);
private:
double m_real;
double m_imag;
};
istream & operator>>(istream & in, MyComplex & com)
{
in >> com.m_real >> com.m_imag;
return in; // 返回值的作用是可以多次使用(istream & in)这个对象。
}
ostream & operator<<(ostream & out, const MyComplex & com)
{
out << "(" << com.m_real << '+' << com.m_imag << 'i' << ')';
return out;
}
int main()
{
MyComplex obj;
MyComplex obj_1;
cin >> obj >> obj_1; // 等价于: operator>>(operator>>(cin, obj), obj_1);
cout << obj << endl
<< obj_1 << endl;
return 0;
}
/** MyComplex **/
MyComplex::MyComplex(double real, double imag)
: m_real(real), m_imag(imag)
{
}
输出:
注意事项
- 运算符重载语法简单,关键是规则
- 可以显示调用(通过函数)也可以隐式调用(通过运算符)
- 注意与友元的联合使用(虽然会破坏封装,但是用起来很爽),可以考虑添加const 关键字,避免友元函数内修改私有数据成员。
<未完待续>