3

我想将一个函数对象传递给一个类,该类将使用该函数对象在类内部完成一些工作。

但问题是,我不知道传入的函数对象是什么。所以我想,void *在类中定义一个指针,这个指针将用传入的函数对象进行初始化。

代码如下:

class A 
{
    public:
        //...
        void doSomeJob(int x)
        {
            (*functor)(x); //use the function object to process data x
        }

    private:
        //...
        void *functor; //function object's pointer will be assigned to this pointer
};

但是代码不起作用。我想,不能这样用void *functor

我知道我可以用它template class来完成这项工作,但我的问题是,我还能用它来完成这项工作pointer to function object吗?怎么做?

附言

为了使我的问题更清楚,可能有几个函数对象在处理数据的方式上彼此不同,我不知道将传入什么函数对象,但我知道它们每个都会接受一个int参数。

正如一些答案所说,我可以通过 来完成这项工作function pointer,但是函数对象比函数指针具有更多的实用程序,例如states,这就是我要使用的。

4

4 回答 4

9

如果函数对象的类型未存储在调用机制可访问的某个位置,则您不能在调用站点调用您不知道的类型的函数对象。

有两种选择:

如果可以使用 C++11 或 boost,则可以使用std::functionresp。boost::function

class A
{
public:
  // ...
  void doSomeJob(int x)
  {
    functor(x);
  }
private:
  std::function<void(int)> functor; // or boost::function when using boost
};

这里类型存储(以隐式形式)在function模板的机制中。

否则,如果您可以要求传递的所有函数对象都具有从特定基类派生的类类型,则可以创建一个抽象基类:

struct AbstractFunctor
{
  virtual void operator()(int) = 0;
};

class A
{
public:
  // ...
  void doSomeJob(int x)
  {
    (*functor)(x);
  }
private:
  AbstractFunctor* functor; // or boost::function when using boost
};

这里类型存储在函数对象的虚拟表中。

如果你真的不能使用 boost,你也可以自己写一个类似的解决方案。关键词是“类型擦除”,它基本上是通过从已知的基类(如我的第二个解决方案)动态生成派生对象来工作的,该基类知道对象的类型并可以调用它。它可能大致如下完成(未经测试的代码):

class int_function
{
private:
  struct abstract_forward
  {
    virtual void call(int) = 0;
    virtual abstract_forward clone() const = 0;
    virtual ~abstract_forward() {}
  };
  template<typename Functor> struct forward: abstract_forward
  {
    forward(Functor f): func(f) {}
    void call(int i) { func(i); }
    abstract_forward clone() const { return new forward<Functor>(func); }
    Functor func;
  };
public:
  template<typename Functor> int_function(Functor f)
  {
    forwarder = new forward<Functor>(f);
  }
  int_function(int_function const& other)
  {
    forwarder = other.forwarder->clone();
  }
  int_function& operator=(int_function const& other)
  {
    abstract_forward* newfwd = other.forwarder->clone();
    delete forwarder;
    forwarder = newfwd;
  }
  ~int_function()
  {
    delete forwarder}
  }
  void operator()(int i)
  {
    forwarder->call(i);
  }
private:
  abstract_forward* forwarder;
};

class A
{
public:
  void doSomeJob(int x)
  {
    functor(x);
  }
private:
  int_function functor;
};
于 2012-01-15T09:46:26.007 回答
2
void *functor; //function object's pointer will be assigned to this pointer

这不是函数指针。

你需要的是这样的:

void (*functor)(int); //function pointer

更好的是(在 C++11 中):

#include <functional> //must include this 

std::function<void(int)> functor;

//then use it as:
functor(x);  //not (*functor)(x)
于 2012-01-15T09:40:33.010 回答
1

正确的语法是:

void (*functor)(int);

另请参阅本教程以了解有关声明和使用函数指针的更多信息:http ://www.cprogramming.com/tutorial/function-pointers.html

于 2012-01-15T09:40:49.690 回答
1

C++ 对其类型非常严格,因此不能只使用void*as 函数指针。该指针必须是您调用它的实际函数指针。

你的意思是你不知道会传入什么函数对象?在该示例中,您知道它接受intorint&作为参数并可能返回void,例如,因此您可以将函数指针存储为:

void (*func)(int);

如果您的意思是说您也希望能够存储类成员函数,或者重载的类的实例,那么如果您有 C++11,operator()则可以使用std::functionand std::bindfrom ,或者and :<functional>boost::functionboost::bind

boost::function<void (int)> func;
于 2012-01-15T09:45:11.493 回答