1、形式:返回值 operator符号(参数列表){}
 
2、不能被重载的运算符::: 作用域运算符  .*   . 成员访问运算符   ?: 条件运算符;某些运算符(逗号,,取地址&,逻辑或||,逻辑与&&)不应该被重载:1)重载之后无法保留运算对象的求值顺序,比如逻辑与&&,逻辑或||和逗号运算符;2)无法保留运算符的短路求值属性,比如&&和||;3)有特殊含义的运算符,比如逗号和取地址。
 
3、建议:只有当操作的含义对于用户来说清晰明了时才使用运算符,否则运算符将产生二义性。
 
4、两种选择:作为类的成员函数或者作为普通的非成员函数
 
5、重载输出运算符
//定义
ostream& operator<<(ostream &os, const Sales_data &item) {
os << item.isbn() <<" "<<item.units_sold<< "——重载输出运算符";
return os;
}
1)尽量减少格式化操作
2)输入输出运算符必须是非成员函数
3)IO运算符一般被声明为友元
friend ostream& operator<<(ostream&, const Sales_data&);
friend istream& operator >> (istream&, Sales_data&);

6、重载输入运算符

//重载输入运算符
istream& operator >> (istream &is, Sales_data &item) {
double price;
is >> item.bookNo >> item.units_sold >> price;
if (is) //检查输入是否成功
item.revenue = item.units_sold*price;
else
item = Sales_data();//输入失败:对象赋予默认状态
return is;
}

调用

/*重载运算符操作,调用*/
Sales_data sales_data;
operator >> (cin, sales_data);//输入
operator<< (cout, sales_data)<<endl;//输出

1)输入运算符必须处理输入可能失败的情况,而输出运算符不需要

7、算数和关系运算符
1)通常情况下,我们把算数和关系运算符定义成非成员函数,以允许对左侧或右侧的运算对象进行转换。
2)相等和不等关系运算符
//相等运算符——包括相等和不等判断,要求所有数据成员对应相等
bool operator==(const Sales_data &lhs, const Sales_data &rhs) {
return lhs.isbn() == rhs.isbn()&&lhs.units_sold==rhs.units_sold&&lhs.revenue==rhs.revenue;
}
bool operator!=(const Sales_data &lhs, const Sales_data &rhs) {
return !(lhs == rhs);
}

3)大于小于关系运算符:如果存在唯一一种可靠的<定义,则应该考虑为这个类定义<运算符。如果类同时还包含==,则当且仅当<的定义和==产生的结果一致时才定义<运算符。也就是说,只要不是==,就一定有一个小于另一个。

8、赋值和复合赋值运算符
 
1)无论形参是什么,赋值运算符都必须定义为成员函数。
//赋值运算符
StrVec& StrVec::operator=(initializer_list<string> il) {
//alloc_n_copy分配内存空间并从给定范围内靠背元素
auto data = alloc_n_copy(il.begin(), il.end());
free();
elements = data.first;
first_free = cap = data.second;
return *this;
}

2)复合赋值运算符定义在类的内部,两者都返回左侧运算对象的引用

//复合赋值运算符
Sales_data& Sales_data::operator+=(const Sales_data &rhs) {
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;
}
9、算数运算符
 
1)算术运算符定义为非成员函数,通常使用定义的复合赋值运算符来定义对应的算术运算符,这样可以简化过程。
//算数运算符--返回对象的拷贝
Sales_data operator+(const Sales_data &lhs, const Sales_data &rhs) {
Sales_data sum = lhs;
sum += rhs;
return sum;
}
10、下标运算符
 
1)下标运算符必须是成员函数。
2)如果一个类包含下标运算符,则它通常会定义两个版本:一个返回普通引用,另一个是类的常量成员并返回常量引用。
//下标运算符
string& StrVec::operator[](size_t n) {
return elements[n];
}
const string& StrVec::operator[](size_t n) const{
return elements[n];
}
11、递增和递减运算符
 
1)前置递增和递减
StrBlobPtr& StrBlobPtr::operator++() {
check(curr,"increment past end of StrBlobPtr");//如果已经指向了容器的尾后位置,那么无法继续递增它
++curr;
return *this;
}
StrBlob& StrBlobPtr::operator--() {
--curr;
check(curr, "decrement past end of StrBlobPtr");
return *this;
}
a、递增和递减应该同时定义前置版本和后置版本,通常应该定义为类的成员函数。
b、为了区分前置和后置运算符,后置版本接受一个额外的(不被使用)int类型的形参。
c、后置操作调用了前置操作。
d、为了与内置版本保持一致,前置运算符返回对象的引用,而后置运算符返回原来对象的一个拷贝。
 
2)后置递增和递减
//后置递增和递减
StrBlobPtr StrBlobPtr::operator++(int) {
StrBlobPtr ret = *this;
++(*this);//调用前置的操作
return ret;
}
StrBlobPtr StrBlobPtr::operator--(int) {
StrBlobPtr ret = *this;
--(*this);
return ret;
}

3)调用

//重载前置和后置递增递减运算符
StrBlobPtr p;
p.operator++();//调用后置运算符
p.operator++();//调用前置运算符
12、成员访问运算符
 
1)箭头运算符必须是类的成员函数,解引用运算符通常也是。
2)因为访问成员不会改变对象状态,所以定义为const。
3)注意箭头运算符的限定,P505
//成员访问运算符
string& StrBlobPtr::operator*()const {
auto p = check(curr, "dereference past end");
return (*p)[curr];
}
string* StrBlobPtr::operator->()const {
//将实际工作委托给解引用运算符
return &(this->operator*());
}
 

[C++] 重载运算符与类型转换(1)的更多相关文章

  1. C++ Primer : : 第十四章 : 重载运算符与类型转换之类型转换运算符和重载匹配

    类型转换运算符 class SmallInt { public: SmallInt(int i = 0) : val(i) { if (i < 0 || i > 255) throw st ...

  2. [C++ Primer] : 第14章: 重载运算符与类型转换

    基本概念 重载运算符是具有特殊名字的函数: 它们的名字由关键字operator和其后要定义的运算符号共同组成. 重载运算符函数的参数数量与该运算符作用的运算对象数量一样多. 对于二元运算符来说, 左侧 ...

  3. 【C++】C++中重载运算符和类型转换

    输入输出运算符 输入输出运算符 输入输出运算符 算术和关系运算符 相等运算符 关系运算符 赋值运算符 复合赋值运算符 下标运算符 递增和递减运算符 成员访问运算符 函数调用运算符 lambda是函数对 ...

  4. [C++] 重载运算符与类型转换(2)——函数调用运算符和类型转换运算符

    1.这两个应该是C++中比较高级的用法了. 一.函数调用运算符   1.重载函数调用运算符(),必须是成员函数,一个类可以定义多个不同版本的调用运算符,相互之间应该在参数数量或者类型上有所区别.   ...

  5. C++ Pirmer : 第十四章 : 重载运算符与类型转换之函数调用运算符与标准库的定义的函数对象

    函数调用运算符 struct test { int operator()(int val) const { return (i > 0 ? i : -i); } }; 所谓的函数调用就是一个类重 ...

  6. c/c++ 重载运算符 类型转换运算符

    重载运算符 类型转换运算符 问题:能不能把一个类型A的对象a,转换成另一个类型B的对象b呢?? 是可以的.这就必须要用类型A的类型转换运算符(conversion operator) 下面的opera ...

  7. C/C++ 运算符重载、数据类型转换

    1.运算符就是“+”.“>>”等符号,对运算符重载实质就是对函数的重载,这样运算符就能在原有基础上增加新功能,不能自己定义新运算符,只能对已有运算符重载,重载运算符后不能改变运算符本身的特 ...

  8. # c++运算符重载之 前置++, 后置++, 负号运算符, 类型转换函数, 以及输入输出运算符

    c++运算符重载之 前置++, 后置++, 负号运算符, 类型转换函数, 以及输入输出运算符 标签(空格分隔): c++ 前言 我在c++学习的过程中, 对这几个不太常见的运算符重载不太会写.出现了很 ...

  9. C++ Primer : 第十四章 : 重载运算与类型转换之重载运算符

    重载前须知 重载运算符是特殊的函数,它们的名字由operator和其后要重载的运算符号共同组成. 因为重载运算符时函数, 因此它包含返回值.参数列表和函数体. 对于重载运算符是成员函数时, 它的第一个 ...

随机推荐

  1. nginx单机1w并发优化

    目录 ab工具 整体优化思路 具体的优化思路 编写脚本完成并发优化配置 性能统计工具 tips 总结 ab工具 ab -c 10000 -n 200000 http://localhost/index ...

  2. Spring源码剖析开篇:什么是Spring?

    在讲源码之前,先让我们回顾一下一下Spring的基本概念,当然,在看源码之前你需要使用过spring或者spirngmvc. Spring是什么 Spring是一个开源的轻量级Java SE(Java ...

  3. Java网络编程 -- NIO非阻塞网络编程

    从Java1.4开始,为了替代Java IO和网络相关的API,提高程序的运行速度,Java提供了新的IO操作非阻塞的API即Java NIO.NIO中有三大核心组件:Buffer(缓冲区),Chan ...

  4. 90002CAD相关操作

    第一章   初识CAD 1.1 CAD能干什么 (1)绘制机械图/建筑图/装修图等二维复杂工程图的不二之选.二维设计软件的王者. (2)CAD可以绘制平面图.轴测图(二维线框表示三维图形).立体图(三 ...

  5. Linux 设置服务开机启动

    首先来了解一下 service命令是Redhat Linux兼容的发行版中用来控制系统服务的实用工具,它以启动.停止.重新启动和关闭系统服务,还可以显示所有系统服务的当前状态. service +(自 ...

  6. JAVA实现读取图片

    话不读说  直接上代码 package cn.kgc.ssm.common; import java.io.*; /** * @author * @create 2019-08-15 9:36 **/ ...

  7. 图解Nginx限流配置

    本文以示例的形式,由浅入深讲解Nginx限流相关配置,是对简略的官方文档的积极补充. Nginx限流使用的是leaky bucket算法,如对算法感兴趣,可移步维基百科先行阅读.不过不了解此算法,不影 ...

  8. HTML(五)列表,区块,布局,表单和输入

    HTML 列表 无序列表 Coffee Tea Milk 默认是圆点,也可以 圆圈 正方形 有序列表 Coffee Tea Milk Coffee Tea Milk 默认是用数字排序 大写字母 小写字 ...

  9. MySQL如何选择合适的索引

    先来看一个栗子 EXPLAIN select * from employees where name > 'a'; 如果用name索引查找数据需要遍历name字段联合索引树,然后根据遍历出来的主 ...

  10. 牛客练习赛39 D 动态连通块+并查集 X bitset 优化

    https://ac.nowcoder.com/acm/contest/368/D 题意 小T有n个点,每个点可能是黑色的,可能是白色的.小T对这张图的定义了白连通块和黑连通块:白连通块:图中一个点集 ...