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. 2019-SUCTF-web记录

    1.web1-chkin 首先发现服务器中间件为nginx,并且fuzz上传过滤情况,是黑名单,带ph的全部不能上传切对文件内容中包含<?进行过滤,并且服务器对文件头有exif_type的判断, ...

  2. ip地址、域名、DNS、URL的区别与联系

    IP:每个连接到Internet上的主机都会分配一个IP地址,此ip是该计算机在互联网上的逻辑地址的唯一标识,计算机之间的访问就是通过IP地址来进行的.写法:十进制的形式,用“.”分开,叫做“点分十进 ...

  3. python 之os模块用法大全

    Python的标准库中的os模块包含普遍的操作系统功能.这个模块的作用主要是提供与平台无关的功能.也就是说os模块能够处理平台间的差异问题,使得编写好的程序无需做任何改动就能在另外的平台上运行 这边给 ...

  4. c++智能指针介绍

    C++11标准引入了boost库中的智能指针,给C++开发时的内存管理提供了极大的方便.接下来这篇文件介绍shared_ptr/weak_ptr内部实现原理及使用细节. C++不像java有内存回收机 ...

  5. java代码实现搜索elasticsearch索引数据

    1.关于获取客户端以及增删改操作请看上一篇文章,文章中有详细的讲解 2.本篇文章讲述关于elasticsearch搜索匹配方式,主要有 match.match_phrase.term.regexp.w ...

  6. 三维动画形变算法(Laplacian-Based Deformation)

    网格上顶点的Laplace坐标(均匀权重)定义为:,其中di为顶点vi的1环邻域顶点数. 网格Laplace坐标可以用矩阵形式表示:△=LV,其中,那么根据网格的Laplace坐标通过求解稀疏线性方程 ...

  7. Log4j2源码分析系列:(一)配置加载

    前言 在实际开发项目中,日志永远是一个绕不开的话题.本系列文章试图以slf4j和log4j2日志体系为例,从源码角度分析日志工作原理. 学习日志框架,首先要熟悉各类日志框架,这里推荐两篇文章,就不再赘 ...

  8. spring boot环境配置

    Eclipse+Maven创建webapp项目<一> 1.开启eclipse,右键new——>other,如下图找到maven project 2.选择maven project,显 ...

  9. 给手机端页面留一个调试后门吧(vue)

    当我们在浏览器开发vue页面时,由于浏览器对于调试有天然的支持,我们开发起来很方便.但是现在已经进入了移动端时代,移动端页面的需求越来越大. 在开发移动端页面的时候我们通常是在浏览器完成开发完成,之后 ...

  10. 微擎 人人商城 导出excel表分析

    在 数据处理上 ,有很多时候需要导出excel表  来当报表, 等 ,  php  人人商城导出报表过程简单分析 在导出时候发现 ca('statistics.order.export'); 出于好奇 ...