这一章重载运算符和类型转换比较简单,直接看书理解就行。
但也比较容易出现错误,仔细看书就行。
重载运算符和类型转换是为了更好的使用类型,即使没有不使用这个技术也不影响。
下面说一下函数调用运算符:()
如果类重载了函数调用运算符,则我们可以像使用函数一样使用该类的对象。
因为这样的类同时也能存储状态,所以与普通函数相比它们更灵活。例如:
struct absInt
{
int operator()(int val) const //返回绝对值
{
return val<0 ? -val : val;
}
};
int i = -3;
absInt obj;
int ui = obj(i); //等价于:obj.operator()(i); 就是函数调用
我们可以调用obj,即使obj只是一个对象而非函数。
***调用对象实际上是在运行重载的调用运算符:本例中,该运算符接受一个int值并返回其绝对值。
函数调用运算符必须是成员函数。一个类可以定义多个不同版本的调用运算符,相互之间应该在参数数量或类型上有所区别。
如果类定义了调用运算符,则该类的对象称作函数对象。因为可以调用这种对象,所以说这些对象的行为像函数一样。
含有状态的函数对象类
函数对象类也可以包含其他成员,函数对象类通常含有一些数据成员,这些成员被用于定制调用运算符中的操作。例如:
class PrintString //打印字符串,并在末尾添加指定字符
{
public:
PrintString(ostream &o = cout, char c = ' '):os(o),sep(c) {}
void operator()(const string &s) const {os< vec{ "abc","aoe","qwer" };
for_each(vec.begin(), vec.end(), PrintString(cerr,'n'));
等价于:第三个参数传递一个函数对象,上面是通过构造函数直接构造,下面是先构造,再传给形参
PrintString print(cerr,'n');
for_each(vec.begin(), vec.end(), print);
lambda是函数对象
当我们编写一个lambda后,编译器将该表达式翻译成一个未命名类的未命名对象。
在lambda表达式产生的类中含有一个重载的函数调用运算符:
如上面的例子用lambda重写:
for_each(vec.begin(),vec.end(),[](const string& s){cout<
public:
void operator()(const string& s) const
{cout< return a.size() >= size; });
该lambda表达式产生的类将形如:
class SizeComp
{
public:
SizeComp(size_t n):size(n){} //对应的捕获的变量
bool operator()(const string& s) const //该调用运算符的返回类型、形参和函数体斗鱼lambda一致
{ return s.size() >= size; }
private:
size_t size; //对应的捕获的变量
};
lambda表达式产生的类不含默认构造函数、赋值运算符及默认析构函数;它是否含有默认的拷贝/移动构造函数则通常要视捕获的
数据成员类型而定。
标准库定义的函数对象
在算法中使用标准库函数对象
重点:可调用对象与function
不同类型可能具有相同的调用形式
学过C#的同学知道,委托和这个功能类似。
自己简单实现类似C#委托的功能:比较简陋,只是提供一个思路
class Action
{
typedef function Fun; //函数类型是无返回值,接受一个int参数
public:
void operator()(int value) //重载函数调用运算符
{
for (auto fun : vec)
{
fun(value);
}
}
void operator+=(Fun fun) //重载+=运算符
{
vec.push_back(fun);
}
//这里不注释会报错,
private:
vector vec;
};
void Test(int i) //一般函数
{
cout << "Test" << i << endl;
}
struct Test2
{
void operator()(int i) //函数对象
{
cout << "Test2" << i << endl;
}
};
void main()
{
Action myAction;
myAction += [] (int a) { cout << "lambda" << a << endl; }; //lambda表达式
myAction += Test;
myAction += Test2();
myAction(666); //利用函数对象执行调用
}
上面会报错的代码的原因:
find会进行==比较两个函数原型void(int),因为没有重载找不到,所以报错。
可以自己重载==操作,但现在还不知道怎么判断两个相同函数原型的函数的相等性



