运算符重载本质上就是函数,可以看做是一个具有特殊名字的函数,所以他和其他函数一样,有返回值,参数,函数体。
如下:是一个运算符重载。operator是关键字。
重载运算符几个要注意的特点
运算符重载的方式有3种:
(1)作为类的成员函数的运算符重载
(2)作为非成员函数运算符重载
1)作为类的友元函数运算符重载
2)普通的函数的运算符重载
这2种的区别是,(1)作为类的成员时会有隐性的this指针作为它的一个参数,所以会比友元和普通函数时少一个参数。
(2)作为友元时参数可以强转操作,作为成员函数时则不能。
不能重载的运算符有4个,跟分别是 :: . * ? : 。
不建议重载的运算符有 逻辑与&,逻辑或|, 逗号运算符,&&, ||。
重载输入输出运算符
重载输入输出要注意的几点:
- 注意:iostream不能复制,所以返回值要用&
- 输入输出一定不能是成员函数,要是非成员函数(友元或者普通函数)
- 重载输出,因为不能更改对象,最好使用const =》 const A& str
- 输入运算符要处理可能失败的情况
#include <iostream>
#include <string>
using namespace std;
class A
{
public:
int i;
double j;
string str;
A(int a, int b, string c) :i(a), j(b), str(c)
{
cout << "hai,i am a A" << endl;
//cout << "i = "<< i << " j = " << j << " str = " << str << endl;
}
};
//注意:iostream不能复制,所以返回值要用&
//输入输出一定不能是成员函数,要是非成员函数(友元或者普通函数)
//重载输出,因为不能更改对象,最好使用const =》 const A& str
//输入运算符要处理可能失败的情况
ostream& operator<<(ostream& os, A& str)
{
os <<"operator "<< str.i << " " << str.j << " " << str.str << endl;
return os;
}
istream& operator>>(istream& is, A& str)
{
is >> str.i >> str.j >> str.str;
if(is)
//处理函数
return is;
}
int main()
{
A a(1, 2, "hello world");
cout << a;
cin >> a;
cout << a;
}
重载相等,算数关系运算符
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class A
{
friend bool operator==(const A& a, const A& b);
friend bool operator!=(const A& a, const A& b);
public:
int i;
double j;
string str;
vector<string> vec;
// ......
//注意:建议==运算符写为友元
bool operator==(const A& a, const A& b)
{
return (a.i == b.i) && (a.j == b.j) && (a.str == b.str);
}
//注意:!=和==正好相反,可以使用它作为实现
bool operator!=(const A& a, const A& b)
{
return !(a == b);
}
//使用i的值作为A的大小比较,小的那放为小
bool operator<(const A& a, const A& b)
{
return a.i < b.i;
}
重载算数运算符
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class A
{
friend bool operator==(const A& a, const A& b);
friend bool operator!=(const A& a, const A& b);
public:
int i;
double j;
string str;
vector<string> vec;
//......
//注意:算数运算符最好为非成员函数,这样得以进行参数对象的转换
//算数运算符的结果往往作为右值,所以不用返回&
//如果要定义想关的复合运算符时, 应该 先定义复合运算符,在使用符合运算符实现算数运算符
A operator+(const A& a, const A& b)
{
A sum;
sum.i = a.i + b.i;
sum.j = a.j + b.j;
sum.str = a.str + b.str;
return sum;
}
重载赋值运算符
class A
{
friend bool operator==(const A& a, const A& b);
friend bool operator!=(const A& a, const A& b);
public:
int i;
double j;
string str;
vector<string> vec;
//......
//注意:赋值运算符必定是成员函数
//赋值运算符分为拷贝和移动赋值运算符
//如果变量类型是指针时,还要处理 原来指向的内存 ,自赋值,移动赋值赋值后赋值的指针指向空
//如果变量类型是指针时,要考虑是行为像指针还是行为像值。
A(const A& a) :i(a.i), j(a.j), str(a.str),vec(a.vec) {}
A& operator=(const A& a)
{
i = a.i;
j = a.j;
str = a.str;
return *this;
}
//移动赋值
A& operator=(A&& a) noexcept
{
//要先判断是不是自己,毕竟自己移动不了自己
if (this != &a)
{
//如果是指针类型,释放原有内存
i = a.i;
j = a.j;
str = a.str;
//将a内存指向空
}
return *this;
}
重载前++, 后++运算符
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class A
{
friend bool operator==(const A& a, const A& b);
friend bool operator!=(const A& a, const A& b);
public:
int i;
double j;
string str;
vector<string> vec;
//......
//++ --建议设为成员函数
//前++和后++的区别是后++会有参数传入(不需要参数名,因为该参数不会使用,仅仅用来区分)
//前++要检查是否超过容器尾部
//前--要检查是否到达容器首部
A& operator++()
{
//这里通常还需要检查是否到达容器尾部,保证++操作安全
++i;
return *this;
}
A& operator--()
{
--i;
//这里通常还需要检查是否到达容器首部,保证--操作安全
return *this;
}
A& operator++(int)
{
A a = *this; //保存当前状态
++*this;
return a;
}
A& operator--(int)
{
A a = *this; //保存当前状态
--*this;
return a;
}
重载下标运算符
。。。。。。