【C++】《C++ Primer 5th》笔记-Chapter14-重载运算与类型转换

笔记:
一、基本概念
1、当一个重载的运算符是成员函数时,this绑定到左侧运算对象。成员运算符函数(显式)参数数量比运算对象的数量少一个。
2、通常情况下,不应该重载逗号、取地址、逻辑与、逻辑或运算符。
3、下面的准则有助于我们在将运算符定义为成员函数还是普通的非成员函数做出抉择:
①赋值(=)、下标([])、调用(())和成员访问箭头(->)运算符必须是成员。
②复合赋值运算符一般来说应该是成员,但并非必须,这一点与赋值运算符略有不同。
③改变对象状态的运算符或者与给定类型密切相关的运算符,如递增、递减和解引用运算符,通常应该是成员。
④具有对称性的运算符可能转换任意一端的运算对象,例如算术、相等性、关系和位运算符等,因此它们通常应该是普通的非成员函数。

二、输入和输出运算符
1、通常,输出运算符应该主要负责打印对象的内容而非控制格式,输出运算符不应该打印换行符。
2、与iostream标准库兼容的输入输出运算符必须是普通的非成员函数,而不能是类的成员函数。
当然,IO运算符通常需要读写类的非公有数据成员,所以IO运算符一般被声明为友元。
3、输入运算符必须处理输入可能失败的情况,而输出运算符不需要。

三、算术和关系运算符
1、通常情况下,我们会把算术和关系运算符定义成非成员函数以允许对左侧或右侧的运算对象进行转换。因为这些运算符一般不需要改变运算对象的状态,所以形参都是常量的引用。
2、如果类同时定义了算术运算符和相关的复合赋值运算符,则通常情况下应该使用复合赋值来实现算术运算符。
3、相等运算符和不相等运算符中的一个应该把工作委托给另外一个,这意味着其中一个运算符应该负责实际比较对象的工作,而另一个运算符则只是调用那个真正工作的运算符。
4、如果某个类在逻辑上有相等性的含义,则该类应该定义operator==,这样做可以使得用户更容易使用标准库算法来处理这个类。
5、如果存在唯一一种逻辑可靠的<定义,则应该考虑为这个类定义<运算符。如果类同时还包含==,则当且仅当<的定义和==产生的结果一致时才定义<运算符。

四、赋值运算符
1、我们可以重载赋值运算符。不论形参的类型是什么,赋值运算符都必须定义为成员函数。而复合赋值运算符不非得是类的成员。
赋值运算符必须定义成类的成员,复合赋值运算符通常情况下也应该这样做。这两类运算符都应该返回左侧运算对象的引用。

五、下标运算符
1、下标运算符必须是成员函数。
2、如果一个类包含下标运算符,则它通常会定义两个版本:一个返回普通引用,另一个是类的常量成员并且返回常量引用。

六、递增和递减运算符
1、C++并不要求递增和递减运算符必须是类的成员,但是因为它们改变的正好是所操作对象的状态,所以建议将其设定为成员函数。
2、定义递增和递减运算符的类应该同时定义前置版本和后置版本。这些运算符通常应该被定义成类的成员。
3、为了与内置版本保持一致,前置运算符应该返回递增或递减后对象的引用。
4、前置和后置版本使用的是同一个符号,意味着其重载版本所用的名字将是相同的,并且运算对象的数量和类型也相同。为了解决这个问题,后置版本接受一个额外的(不被使用)int类型的形参。当我们使用后置运算符时,编译器为这个形参提供一个值为0的实参。尽管从语法上来说后置函数可以使用这个额外的形参,但是在实际过程中通常不会这么做。这个形参的唯一作用就是区分前置版本和后置版本的函数,而不是真的要在实现后置版本时参与运算。
5、为了与内置版本保持一致,后置运算符应该返回对象的原值(递增或递减之前的值),返回的形式是一个值而非引用。

七、成员访问运算符
1、箭头运算符必须是类的成员。解引用运算符通常也是类的成员,尽管并非必须如此。
2、重载的箭头运算符必须返回类的指针或者自定义了箭头运算符的某个类的对象。

八、函数调用运算符
1、函数调用运算符必须是成员函数。一个类可以定义多个不同版本的调用运算符,相互之间应该在参数数量或类型上有所区别。
2、如果类定义了调用运算符,则该类的对象称为函数对象。因为可以调用这种对象,所以我们说这些对象的"行为像函数一样"。
3、函数对象常常作为泛型算法的实参。
4、当我们编写了一个lambda后,编译器将该表达式翻译成一个未命名类的未命名对象。在lambda表达式产生的类中含有一个重载的函数调用运算符。
默认情况下,lambda不能改变它捕获的变量。因此在默认情况下,由lambda产生的类当中的函数调用运算符是一个const成员函数。如果lambda被声明为可变的,则调用运算符就不是const的了。
5、lambda表达式产生的类不含默认构造函数、赋值运算符及默认析构函数;它是否含有默认的拷贝/移动构造函数则通常要视捕获的数据成员类型而定。
6、标准库定义了一组表示算术运算符、关系运算符和逻辑运算符的类,每个类分别定义了一个执行命名操作的调用运算符。这些类都被定义模板的形式,我们可以为其指定具体的应该类型,这里的类型即调用运算符的形参类型。
7、C++语言中有几种可调用的对象:函数、函数指针、lambda表达式、bind创建的对象以及重载了函数调用运算符的类。

九、重载、类型转换与运算符
1、转换构造函数和类型转换运算符共同定义了类类型转换,这样的转换有时也被称作用户定义的类型转换。
2、类型转换运算符是类的一种特殊成员函数,它负责将一个类类型的值转换成其他类型。
类型转换运算符既没有显式的返回类型,也没有形参,而且必须定义成类的成员函数。类型转换运算符通常不应该改变待转换对象的内容,因此,类型转换运算符一般被定义成const成员。
3、向bool的类型转换通常用在条件部分,因此operator bool一般定义成explicit的。
4、通常情况下,不要为类定义相同的类型转换,也不要在类中定义两个及两个以上转换源或转换目标是算术类型的转换。
5、当我们使用两个用户定义的类型转换时,如果转换函数之前或之后存在标准类型转换,则标准类型转换将决定最佳匹配到底是哪个。

一些术语:
1、赋值、下标、函数调用和箭头运算符必须作为类的成员。
2、如果类重载了函数调用运算符operator(),则该类的对象被称作"函数对象"。这样的对象常用在标准函数中。lambda表达式是一种简便的定义函数对象类的方式。
3、显式的类型转换运算符:由关键字explicit限定的类型转换运算符。这样的运算符用于条件中的隐式类型转换。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值