重载运算与类型转换(二)
函数调用运算符
//函数调用运算符
struct absInt
{
int operator() (int val) const{
return val < 0 ? -val : val;
}
};
函数调用运算符必须是成员函数,一个类可以定义多个不同版本的调用运算符,相互之间应该在参数数量或类型上有所区别
一个重载的调用运算符应该接受0个或多个运算对象
lambda表达式
一个lambda表达式表示一个可调用的代码单元,可以理解成一个未命名的内联函数。
[capture list] (parameter list) -> return type {function body}
//capture list为捕获列表,是一个lambda所在函数中定义的局部变量的列表,一般为空。
//其余三个表示返回值类型,参数列表,函数体。
//lambda必须使用尾置返回来指定返回值类型 尾置返回类型跟在形参后面并以一个->符号开头
stable_sort(words.begin(),words.end(),[]()const string &a,const string &b)
{return a.size()<b.size();};//lambda表达式
class ShortString
{
public:
bool operator()(const string &s1,const string &s2) const
{return s1.size()<s2.size();}
};
用ShortStraing替代lambda表达式,重写stable_sort
stable_sort(words.begin(),words.end(),ShortString());
标准库定义的函数运算对象
//
count_if(vec.begin(),vec.end(),bind2nd(greater<int>(),1024));
//使用标准库函数对象及适配器定义一条表达式
//统计大于1024的值有多少个
find_if(vec.bigin(),vec.end(),bind2nd(not_equal<string>(),'pooh'));
//找到一个不等于pooh的字符串
transform(vec.begin(),vec.end(),bin2nd(multiplities<int>(),2));
//将所有值乘以2
重载、类型转换与运算符
类型转换运算符是类的的一种特殊成员函数,负责将一个类类型值转换成其他类型。
//
operator type() const;
/type表示某种类型。类型转换符可以面向任意类型(除了void之外)进行定义,只要该类型能作为函数的返回类型。
/类型转换运算符没有显示的返回类型,也没有形参,而且必须定义成类的成员函数。
//
//显示的类型转换运算符
class SmallInt()
{
public:
//编译器不会自动执行这一类型转换
explicit operator int() const { return val;}
//其他成员与之前的版本一致
}
SmallInt si = 3;
si+3;//错误,此处需要隐式的类型转换,但类的运算符是显式的
static_cast<int>(si) + 3;//正确,显式的请求类型转换
但是存在一个例外,如果表达式被用作条件,则编译器会将显示的类型转换自动应用于它。
if/while/do/语句的条件部分
for语句的开头条件表达式
逻辑运算符!/||/&&的运算对象
条件运算符(?:)的条件表达式
避免有二义性的类型转换
一般来说,不要为类定义相同的类型转换,也不要在类中定义两个及两个以上转换源或转换目标是算术类型的转换
当我们使用两个用户定义的类型转换时,如果转换函数之前或之后存在标准类型转换,则标准类型转换将决定最佳匹配到底式哪一个。
如果我们对一个类既提供了转换目标是算术类型的转换,也提供了重载的运算符,则将会遇到重载运算符与内置运算符的二义性问题。
//
class SmallInt
{
friend SmallInt operator+(const SmallInt&,const SmallInt&,);
public:
SmallInt(int = 0);
operator int() const {retuen val;}
private:
std::size_t val;
};
SmallInt s1,s2;
SmallInt s3=s1+s2;//使用operator+
int i=s3+0;//二义性,既可以使用构造函数将0转换成SmallInt,然后使用SmallInt的+,也可使把S3转换成int,然后通过内置+
//