操作重载与类型转换
重载的运算符是具有特殊名字的函数。 operator <type>
一元运算符有一个参数, 二元两个。除了重载函数的调用运算符 operator()
之外,其他重载运算符不能含有默认实参。
如果是类的成员函数, 则第一个运算对象绑定到隐试的 this
指针上。
不能被重载的运算符:
:: | .* | . | ?: |
---|
在通常情况下,不应该重载逗号,取地址,逻辑运算符。
在把重载运算符定义成成员函数时, 注意运算对象的顺序。(两种不需顺序的方法:1. 定义成非成员函数; 2. 给相应的类定义类型转换)
函数调用运算符
如果类定义了调用运算符,则该类可以称作函数对象
lambda是函数对象
标准库函数对象:
算数 | 关系 | 逻辑 |
---|---|---|
plus | equal_to | logical_and |
minus<> | not_equal_to<> | logical_or<> |
multiplies<> | greater<> | logical_not<> |
divides<> | greater_equal<> | |
modulus<> | less<> | |
negate<> | less_equal<> |
(标准库的函数对象对于指针也是适用的,自己定义的 函数对象 将会产生未定义行为)
returnType (argv1Type, argv2Type, ...)
构成了一种调用形式(call signature)。
定义一个 map<string, function<call_signature> >
可以形成一个函数表,然后使用函数表简化调用过程。
重载、类型转换
转换构造函数 和 类型转换运算符 共同定义了 类类型转换 ,也叫作 用户定义类型转换
operator type() const;
必须是成员函数,不能声明返回类型,形参列表必须为空。
explicit operator type() const
显示的类型转换运算符。在转换类类型时需显示的指出。
定义这类类类型转换运算符, 很容易造成二义性问题。尽量避免 class A -> class B, class B -> class A 等之类的情况出现(避免出现类型转换图上有环??)。