C中的异构函数指针数组

Array of heteregenous function pointers in C

本文关键字:指针 数组 函数 异构      更新时间:2023-10-16

我想要一个函数指针数组,每个指针指向不同的函数。该函数在原型和参数数量方面也可能有所不同。

我正在C/C++中寻找以下类似的功能。

以下代码在C 中不可编译

#include <stdio.h>
typedef int (*FUNC)(int a,int b);
int func_one(int a)
{
   printf("n In function 1 with 1 parameter %d n",a);
   return 1;
}
int func_two(int a,int b)
{
   printf("n In function 2 with 2 parameter %d %d n",a,b);
   return 2;
}
typedef struct{
FUNC fnc;
enum type{ ONE,TWO} type_info;
}STR;
int main()
{
STR str[2];
int ret;
int i;
str[0].fnc = func_one;
str[0].type_info = ONE;
str[1].fnc = func_two;
str[1].type_info = TWO;

for(i=1;i>=0;--i)
{
   if(str[i].type_info == ONE)
      ret = str[i].fnc(10);
   else if(str[i].type_info == TWO)
      ret = (str[i].fnc)(10,20);
   else
      perror("error in implementation n");
       printf("n return value is %d n",ret);
     }
return 0;
}

在C中,从一种函数指针类型转换为另一种是安全的(只要您为了调用它而将其反向转换),因此您可以声明一种"通用函数指针类型":

typedef void (*GENFUNC)(void);

然后根据需要铸造:

GENFUNC tmp = (GENFUNC)&func_two; // cast to generic pointer
FUNC two = (FUNC)tmp; // note: have to cast it back!
two(0, 1);

这似乎不是一个好主意。但如果你真的需要这个,那么你应该考虑使用一个联合:

typedef struct{
    union{
        int (*f1)(int);
        int (*f2)(int,int);
    } fnc;
    enum type{ ONE,TWO} type_info;
}STR;

如果你知道所有不同的可能类型,你可以这样做:

typedef int (*FUNC1)(int a);
typedef int (*FUNC2)(int a,int b);
typedef struct{
    union {
        FUNC1 one_arg;
        FUNC2 two_arg;
    } fnc;
    enum type{ ONE,TWO} type_info;
} STR;

如果你不知道它们,但无论何时使用,你都可以设法找出正确的表格,你可以简单地使用:

typedef struct{
    void *fnc;
    enum type{ ONE,TWO} type_info;
} STR;

或者以非常通用的形式:

typedef struct{
    void *func;
    char *return_type;
    char *args_type;
} STR;

其中CCD_ 1是每个k个字母显示一个可能的参数类型的字符串。与return_type相同,只是它也可以包含void"v"

然后,每当你想使用函数时,你必须查看return_type和args_type,并决定将func大小写为哪个原型。这在某种程度上类似于C++中的名称篡改(尽管使用名称篡改,函数名称本身用args_type符号装饰,而不是保留另一个字符串)

typedef int (*FUNC)(void);
typedef int (*FUNC_1p)(int);
typedef int (*FUNC_2p)(int, int);
typedef struct
{
   FUNC fnc;
   enum type { ONE, TWO } type_info;
} STR;

 if ( str[i].type_info == ONE )
  {
      FUNC_1p f = str[i].fnc;
      ret = f(10);
  }
  else if ( str[i].type_info == TWO )
  {
      FUNC_2p f = str[i].fnc;
      ret = f(10,20);
  }

它编译并运行。不过这不是个好主意。

C中的"泛型"函数将使用一个void*指针,然后必须将void*强制转换为数据。

您可以创建几个不同的特殊类型的版本,这些版本将始终对"已知"类型进行操作,这样它们就可以将void*强制转换为该函数的特定类型,但签名将采用void*参数,这样您就可以在函数数组中存储多个参数。

例如

typedef int (GENERIC_FUNC*)(void* genericData);
struct A
{
    int x;
    int y;
};
int GenericAFunc( void * ptr )
{
    A* a = (A*)(ptr);
    return a->x + a->y;
}
GENERIC_FUNC * funcs[1];
funcs[0] = GenericAFunc;

这些函数都将返回int,但如果您希望它们生成不同的结果集,它们也可以在a结构中设置结果。

将函数定义为接受可变数量的参数:

typedef int (*FUNC)(int a, ...);

然后简单地选一个有趣的:

str[0].fnc = (FUNC) func_one;
str[1].fnc = (FUNC) func_two;

你可以像现在一样调用func:

if(str[i].type_info == ONE)
    ret = str[i].fnc(10);
else if(str[i].type_info == TWO)
    ret = str[i].fnc(10,20);

这是可能的,因为可变参数函数允许您向其传递任意数量的整数。

我不确定这是否符合您的实际需求,但您可以使用从公共基类派生的函子:

#include <cstdio>
struct FUNC {
  enum type {INVALID, ONE, TWO} type_info;
  virtual int operator()(int) { return -1; }
  virtual int operator()(int, int) { return -1; }
  FUNC(type t=INVALID) : type_info(t) {}
};
struct func_one : FUNC {
  func_one() : FUNC(ONE) {}
  int operator()(int) { return 1; }
};
struct func_two : FUNC {
  func_two() : FUNC(TWO) {}
  int operator()(int, int) { return 2; }
};

int main () {
  FUNC* str[2] = { new func_one(), new func_two() };
  int ret;
  int i;
  for(i = 1; i>=0; --i) {
    if(str[i]->type_info == FUNC::ONE)
      ret = (*str[i])(10);
    else if(str[i]->type_info == FUNC::TWO)
      ret = (*str[i])(10,20);
    else
      throw 1;
    printf("Return value is %dn", ret);
  }
}