1

这段代码有什么问题?这段代码给了我很多语法错误。另外我想知道为什么在 C++ 中使用函子。

class f
{
public:
    int operator(int a) {return a;}
} obj;

int main()
{
    cout << obj(0) << endl;
}
4

6 回答 6

7

声明时缺少一对额外的括号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 类似的示例,但展示了如何轻松地将其应用于容器中的一系列元素。

于 2010-09-13T05:35:59.010 回答
0

由于您已经在运算符重载代码中发现了问题,我宁愿尝试解决您对仿函数的疑问。

Functor 是“函数指针”的缩写。这些被广泛用于提供自定义算法行为的句柄,例如 STL 中的排序算法使用函子作为参数,用户(程序员)可以实现该函数来告诉算法两个元素的比较结果。

于 2010-09-13T05:47:20.477 回答
0

仿函数是一个对象(类或结构的实例),通常重载 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;
}
于 2010-09-13T06:04:23.663 回答
0

因为int operator(int)实际上等于 intint #something_missing_here#(int)

operator是一个保留关键字,而不是单独使用时作为有效函数标识符/名称的限定符。
我会说它用于使编译器理解给定的表达式是函数声明,尽管使用了无效的标识符(c++ 只允许字母和下划线作为命名中的第一个字符)

于 2010-09-13T05:43:19.337 回答
0

函子基本上是带有状态的函数。它们最大的用途是在 STL 和 Boost 库中。例如std::sort采用一种称为 的仿函数Comparator。在这种情况下,也许可以传递一个函数对象,但函子通过您可以拥有的数据成员提供了更大的灵活性,并且可以通过对同一函子的后续调用进行操作。函子也用于实现 C++ 回调。

于 2010-09-13T05:46:38.563 回答
-3

尝试这个:

class f
{

  public:

   int operator(int a) {return a;}

};

int main()
{
  f obj;
  cout<<obj(0)<<endl;

}
于 2010-09-13T05:35:44.513 回答