c++运算符重载
-
- 基本概念
-
- 调用方式
- 某些运算符不应该被重载
- 使用与内置类型一致的含义
- 选择作为成员或者非成员
- 输入和输出运算符
-
- 重载输出运算符 <<
- 重载输入运算符 >>
- 算数和关系运算符
-
- 相等运算符
- 关系运算符
- 赋值运算符
- 下标运算符
- 递增和递减运算符
- 函数调用运算符
-
- lambda是函数对象
常忘常看,记录下来以备后忘
基本概念 关键字operator和其后要定义的运算符号共同组成。除了operator()之外,其他不能重载运算符不能有默认参数。
一元运算符只传递一个参数,二元运算符传递两个参数给函数。
一个运算符函数是成员函数,this绑定到左侧运算对象,所以成员运算符(显式)参数数量比运算对象少一个
note:
内置类型不可以重载运算符,且只能重载已有运算符,不能被重载的运算符包括 :: .* . ?:
调用方式
直接用运算符或者直接调用函数
data1 + data2 ,也可以operator(data1, data2)
成员函数时也可以写成data1+= data2 data1.opterator+(data2),其中+= 这个二元操作符的第一个参数是隐式传入的data1
某些运算符不应该被重载
& , 等运算符是有特殊意义的,不建议重载
本质上运算符重载是一次函数调用,所以无法保留求值顺序 短路求值属性,所以不建议重载
使用与内置类型一致的含义
设计类时,考虑类将提供哪些操作,之后再思考把类设成普通函数还是重载的运算符。
- 如果类执行I/O,定义移位运算符与其内置IO保持一致
- 检查相等性,用operator==,有了这个通常也应该有,operator !=
- 类包含一个内在单序比较,定义operator < ,通常应该定义其他关系操作
- 返回类型也应该与其内置版本兼容。逻辑和关系返回bool,算数运算符返回类类型的值,赋值和符合运算符应该返回运算对象的一个引用
- 赋值和复合赋值运算符:返回左侧对象的一个引用
某些时候必须作为成员,但是有些情况,普通函数比成员更好。
- = []以及调用运算符() 以及 -> 必须是成员函数
- 复合赋值类的一般是成员
- 改变对象状态的++ --等 ,通常是成员
- 具有对称性的,通常应该是非成员
通常情况下,第一个参数应该是非常量ostream对象的引用。非常量是因为会改变对象状态,引用是因为ostream对象无法复制
输出运算符应该尽量减少格式化操作,尤其不会打印换行符
通常情况下,它应该主要负责输出内容而非格式
**输入输出运算符必须是非成员函数,否则左侧对象将是我们类的一个对象,我们的格式将会变成data << out。。**如果定义成正常输出方式,我们又无法有来看中stream成员增加函数
所以我们要将输入输出定义成非成员函数,当然因为我们要读写类的非公有数据成员,所以一般要声明为友元
重载输入运算符 >>
通常第一个参数是读取流的引用,第二个参数是非常量的对象的引用,返回值是给定流的引用。
istream & operator >> (istream& is, Data& data)
{
double price;
is >> data.no >> data.sold >> price;
if(is)
{
data.revenue = data.sold * price;
}
else
{
data = https://www.it610.com/article/Data();
}
}
注意:输入运算符必须处理可能失败的情况
算数和关系运算符 一般会定义成非成员函数,因为一般不需用改变运算对象的状态,所以形参都是常量的引用。
相等运算符
如果一个类含有两个对象比较相等的操作,应该定义operator== ,因为符合用户习惯
定义了opterator== , 运算符应该能判定一组给定对象中是否含有重复数据
通常情况下,相等运算符应该有传递性
如果定义了operator==,也应该定义operator !=
operator==,operator != 应该一个运算符委托给另外一个去做,比如,operator != 中返回 ! operator== 的操作
本内容参照c++ primer第四版内容
关系运算符
定义了==的通常也会定义小于运算符,因为关联容器和一些算法需要用到小于运算符,所以定义<比较有用
赋值运算符 和拷贝赋值以及移动赋值一样,重载的赋值函数,应当先释放当前内存空间,然后再创建一片新空间。
下标运算符 必须是成员函数,通常会定义两个版本,一个是返回普通引用,一个返回类的常量成员并返回常量引用
递增和递减运算符 前置operator++() 后置operater++(int) 参数仅用来区分前置后置运算符
函数调用运算符 如果重载了函数调用运算符(),则可以想使用函数一样,使用该类的对象
struct abrInt
{
int operator()(int) const
{
return val < 0 ? -val : val;
}
}int i = 19;
abrInt absObj;
absObj(i);
【C++|【c++运算符重载】】如果类定义了调用运算符,该类对象称为函数对象。即使absObj只是一个对象,也能"调用"该对象。实际上是调用重载的调用运算符。
lambda是函数对象
推荐阅读
- c++|C++之string类(·标准库中的string类·string类的模拟实现)
- C|天天new对象的程序员,居然能找到女朋友(还能教你追女生?)
- c++|NMS 原理和c++实现,已测试通过
- visual|使用 Visual Studio Code 编写你的第一个 C 程序
- VC++|VC++使用画刷绘图 简单画刷 FillRect函数 位图画刷 透明画刷
- VC++|VC++ 利用MFC的CWindowDC类实现画线功能 在桌面窗口中画线 绘制彩色线条 CPen nPenStyle nWidth crColor
- C++基础|【千律】C++基础(ShellExecuteEx 函数的相关使用案例)
- VC++|VC++简单绘图 MFC消息映射机制 MessageBox函数
- VC++|VC++ 类向导