重载 operator() 的类的对象以及函数指针叫函数对象。
类重载 operator() 有一些好处:
- operator() 可以是重载的函数。传递这个函数对象给泛型库时,可以把重载集作为一个整体传过去。而传函数指针的话只能传单体。
- 函数对象可以有状态,这可以实现闭包。 C++ 语核里有 lambda 表达式,它可以创建自动捕获外围变量(或者携带自定义状态)的函数对象。
目前类重载的 operator() 有一些缺点:
- 它不能是 static 成员函数。这使得标准库中大量存在的无状态函数对象,以及可能广泛使用的自定义无状态函数对象,可能会带来额外开销。也使得无捕获的 lambda 实现变得复杂。(至少需要有一个非 static 的 operator() 和 static 的额外成员函数。 Lambda 表达式需要能被隐式转换成指向后者的指针。)
用法为:
class ShorterThan { public: explicit ShorterThan(int maxLength) : length(maxLength) {} bool operator() (const string& str) const { return str.length() < length; } private: const int length; };
- count_if(myVector.begin(), myVector.end(), ShorterThan(length)); //直接调用即可
这里需要注意的是,不要纠结于语法问题:ShorterThan(length)似乎并没有调用operator()函数?其实它调用了,创建了一个临时对象。你也可以自己加一些输出语句看一看。
类型转换
C++中可以定义类型转换函数,将类对象转换为其他类型,函数原型为:operator Type()
- 类型转换函数与转换构造函数具有同等的地位;
- 类型转换函数使得编译器有能力将对象转化为其他类型;
- 编译器能够隐式的使用类型转换函数
#include <iostream> #include <string> class Test; class Value { public: Value() { } Value(Test& t) // false // explicit Value(Test& t) // Ok { std::cout << "explicit Value(Test& t)" << std::endl; } }; class Test { int mValue; public: Test(int i = 0) { mValue = i; } int value() { return mValue; } operator Value() { Value ret; std::cout << "operator Value()" << std::endl; return ret; } }; int main() { Test t(100); Value v = t; return 0; }
从输出结果我们可以发现:转换构造函数和类型转换函数发生冲突了,编译器不知道应该调用哪个函数。因此发生了错误。
当然我们可以使用explicit关键字抑制隐式的转换构造函数,让程序只调用类型转换函数。但是,我们无法抑制隐式的类型转换函数。
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/17533.html