[Cpp基础][10]重载运算符
重载运算符
规定
- 赋值,取下标,调用,箭头,类型转换,这些运算符只能作为成员函数.
- 用户重载的
&&与||不会进行短路求值.
习惯
- 重载主要分为全局重载和类内重载,一般而言,二元运算都应该在全局重载(顺序问题).
- 改变对象状态的运算符一般应当设为成员函数,拥有对称性的运算符一般应在类外重载.
- 从技术层面说,重载运算符的参数可以是指针类型的,但是这一般与我们使用语言的习惯不符,所以形参类型最好只是
T或T&,而不要是指针. - 定义有关联的重载运算符时一定要考虑兼容性,例如
a<b为假,a>b也为假,那么a==b就应该返回真. - 重载中应当尽可能的保持语义与内置风格一致.
- 例如,如果重载了
++运算符,那么应当保证++x和x+=1及x=x+1有同样的效果.
- 例如,如果重载了
- 尽量不要重载全局的
operator new,仅在类内重载它.- 类内重载的
new和delete都是static的,因此,无法使用this相关的量 - 这两个重载只需要负责分配/销毁空间,构造和析构仍然是编译器自动插入代码执行的.
- 类内重载的
- 取地址运算符由于有着明显且通用的意义,一般不应该重载.
解引用和箭头
- 一般只有行为类似于指针的类才重载
->和* ->最终必须返回一个指针p,obj->和p->语义上等价.- 对于
class T1;,若它的重载->返回的不是指针,例如返回一个T3的T3 operator->(),此时会隐含的继续调用T3::operator->(),直到返回一个指针.
- 对于
- 习惯上
*返回某个对象的引用,应当尽可能保证解引用运算符和指针运算符对应同一个对象,以保证(*p).member和p->member总是相互等价的
User-defined-literal
- 我们还可以重载全局
operator "" _myname自定义字面值常量的后缀,例如1001km这样的常量是允许的.
类型转换运算符
- 我们可以定义类型转换运算符,从而指定从当前类转换到其他类时的行为.该函数在类内定义,无需返回类型,形式为
operator TName(){return var_of_tname} - 这种特型十分危险,极易引起二义性的问题,使用时要慎重,一定要避免使用.(例如,习惯上只应定义一个到bool类型的explicit转换)
- 在作为条件时,explicit可以被编译器忽略.
- 替代方案是添加一个
to_tname()成员函数,我们就可以显式的进行转换了.