函数数组包含来自不同对象的函数

function array with functions from different objects

本文关键字:函数 对象 数组 包含      更新时间:2023-10-16

我在c++中没有太多使用数组函数的经验。我需要使用一个函数数组,其中数组包含来自不同对象的函数。下面是一些虚拟代码来说明我想要实现的内容。

class base_class
{
public:
  virtual int function1(int arg1, int arg2);
  virtual int function2(int arg1, int arg2);
};
class derived_class : public base_class
{
public:
  int function1(int arg1, int arg2) { /* ... */ };
  int function2(int arg1, int arg2) { /* ... */ };
  // ...
};
typedef int (*functions) (int arg1, int arg2); 
int main()
{
  derived_class object1;  
  derived_class object2;  
  functions func_instance[4];
  func_instance[0] = object1.function1;
  func_instance[1] = object1.function2;
  func_instance[2] = object2.function1;
  func_instance[3] = object2.function2;
  // ...
}

我不能让它工作,它抛出以下错误:

error: argument of type int () (int , int) does not match int (*) (int, int)

最简单的方法是使用std::functionstd::bind

#include <functional>
#include <array>
derived_class object1;
derived_class object2;
std::array< std::function<int(int, int)>, 2> > 
  arr = {{ std::bind(&derived_class::function1, &object1)
         , std::bind(&derived_class::function2, &object1)}};
         // and so on

注意object1object2已被地址绑定。只要绑定函数存在,你就需要让它们存在。如果在bind表达式中只写object1,对象的副本将存储在绑定函数中,不会出现作用域问题。

c++ 03一个完整的例子,一个手工制作的,单一用途的绑定类型:

#include <iostream>
struct base
{
  virtual void f0() { std::cout << "f0 base" << std::endl; }
  virtual void f1() { std::cout << "f1 base" << std::endl; }
};
struct derived : base
{
  void f0() { std::cout << "f0 derived" << std::endl; }
  void f1() { std::cout << "f1 derived" << std::endl; }
};
// typedef for a Pointer to a member function 
// of base that accepts arguments and returns void
typedef void (base::*MemberPtrType)(void);
// we pack a pointer to a class and a pointer to a member function together
struct binder
{
  MemberPtrType ptr;
  base*         base;
  // shortcut to call this thing, you might also want 
  // to have an overload of operator() and a result_type typedef
  void call()
  { ((base)->*(ptr))(); }
};

int main()
{
  base b;
  derived d;
  // initialize a 4 element array of binder, the first argument is the function,
  // the second is the object to call it on
  // 
  // remember that b and d need to be alive as long as 
  // you want to call something in this array
  binder arr[4] = { {&base::f0, &b}, {&base::f1, &b}, 
                    {&base::f0, &d}, {&base::f1, &d}};
  // now walk through the array and call each
  for(binder* begin = arr; begin != arr + 4; ++begin)
  {
    begin->call();
  }

  return 0;
}