这段代码有什么问题?这段代码给了我很多语法错误。另外我想知道为什么在 C++ 中使用函子。
class f
{
public:
int operator(int a) {return a;}
} obj;
int main()
{
cout << obj(0) << endl;
}
这段代码有什么问题?这段代码给了我很多语法错误。另外我想知道为什么在 C++ 中使用函子。
class f
{
public:
int operator(int a) {return a;}
} obj;
int main()
{
cout << obj(0) << endl;
}
声明时缺少一对额外的括号operator()
。函数名是operator()
,后面还需要参数列表。因此它应该看起来像:
int operator()(int a) {return a;}
像这样的函数对象(又名函子)通常用于您使用指向函数的指针的地方。但是,它们的优点是可以使用继承并且还可以封装状态。通常,设计良好的类或函数模板几乎可以与函数指针互换使用。然而,一个好的优化器通常可以在使用模板对象时生成更好的代码。
有关如何使用函数对象的相当复杂的示例,请查看表达式模板。
这是一个关于他们如何使用继承的小而有点做作的例子:
struct unary_int_func {
virtual int operator()(int i) = 0;
};
struct negate : public unary_int_func {
int operator()(int i) {return -i;}
};
struct one_plus : public unary_int_func {
int operator()(int i) {return i+1;}
};
void show_it(unary_int_func &op, int v) {
cout << op(v) << endl;
}
在这种情况下,我们创建了一个带有操作符的基类作为纯虚函数。然后我们派生出实现它的具体类。这样的代码就show_it()
可以使用从这个基类派生的类的任何实例。虽然我们可以只使用一个指向函数的指针,该函数接受一个 int 并返回一个 int,但这更安全。使用函数指针的代码将接受任何这样的函数指针,而这样我们可以定义一个全新的层次结构,将 int 映射到 int:
struct a_different_base_class {
virtual int operator()(int i) = 0;
};
但是这样的实例不能与 unary_int_func 的实例互换。
至于状态,考虑一个运行求和函数:
struct running_sum : public unary_int_func {
int total;
running_sum() : total(0) {}
int operator()(int i) {return total += i;}
};
int main()
{
running_sum s;
cout << s(1) << endl;
cout << s(2) << endl;
cout << s(3) << endl;
cout << s(4) << endl;
}
在这里,实例running_sum
跟踪总数。它将打印出 1、3、6 和 10。指向函数的指针无法在不同的调用之间保持状态。SGI 的关于函数对象的 STL 页面有一个与我的运行 sum one 类似的示例,但展示了如何轻松地将其应用于容器中的一系列元素。
由于您已经在运算符重载代码中发现了问题,我宁愿尝试解决您对仿函数的疑问。
Functor 是“函数指针”的缩写。这些被广泛用于提供自定义算法行为的句柄,例如 STL 中的排序算法使用函子作为参数,用户(程序员)可以实现该函数来告诉算法两个元素的比较结果。
仿函数是一个对象(类或结构的实例),通常重载 operator()。仿函数和普通函数的区别在于,由于仿函数是一个对象,它可以在调用之间保持状态。
因为仿函数是一个对象,继承规则也适用,你可以利用它来发挥你的优势。
当您使用 STL 时,仿函数也很有用。std::sort、std::for_each 等允许您处理整个容器的内容(包括数组)。以下是来自 cplusplus.com 的示例:
// for_each example
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
void myfunction (int i) {
cout << " " << i;
}
struct myclass {
void operator() (int i) {cout << " " << i;}
} myobject;
int main () {
vector<int> myvector;
myvector.push_back(10);
myvector.push_back(20);
myvector.push_back(30);
cout << "myvector contains:";
for_each (myvector.begin(), myvector.end(), myfunction);
// or:
cout << "\nmyvector contains:";
for_each (myvector.begin(), myvector.end(), myobject);
cout << endl;
return 0;
}
因为int operator(int)
实际上等于 intint #something_missing_here#(int)
operator
是一个保留关键字,而不是单独使用时作为有效函数标识符/名称的限定符。
我会说它用于使编译器理解给定的表达式是函数声明,尽管使用了无效的标识符(c++ 只允许字母和下划线作为命名中的第一个字符)
函子基本上是带有状态的函数。它们最大的用途是在 STL 和 Boost 库中。例如std::sort采用一种称为 的仿函数Comparator
。在这种情况下,也许可以传递一个函数对象,但函子通过您可以拥有的数据成员提供了更大的灵活性,并且可以通过对同一函子的后续调用进行操作。函子也用于实现 C++ 回调。
尝试这个:
class f
{
public:
int operator(int a) {return a;}
};
int main()
{
f obj;
cout<<obj(0)<<endl;
}