【问题标题】:function pointer for different functions with different data types or parameter具有不同数据类型或参数的不同函数的函数指针
【发布时间】:2017-01-04 04:59:13
【问题描述】:

我有这段代码,它使用函数指针指向 3 个函数 sum、subtract、mul。它运作良好。但现在的问题是我的函数具有不同的参数数量和不同的数据类型。如何实现。

int add(int a, int b)
{
    cout<<a+b;
}
int subtract(int a, int b)
{
    cout<<a-b;
}
int mul(int a, int b)
{
    cout<<a*b;
}

int main()
{

    int (*fun_ptr_arr[])(int, int) = {add, subtract, mul};
    unsigned int ch, a = 15, b = 10,c=9;
    ch=2;
    if (ch > 4) return 0;

    (*fun_ptr_arr[ch])(a, b);

    return 0;
}

【问题讨论】:

  • 旁注,你应该检查ch &gt; 2,而不是ch &gt; 4(或者更好的是ch &gt; sizeof(fun_ptr_arr)/sizeof(*fun_ptr_arr)-1)。

标签: c++ function-pointers


【解决方案1】:

简单的答案是,从技术上讲,您无法做到这一点。您可以使用数组作为所有这些函数的输入进行一些操作,但您仍然必须确切知道要传递给每个函数的内容。从软件工程的角度来看,你不应该这样做——我建议你看看这里的好答案:C++ Function pointers with unknown number of arguments

【讨论】:

    【解决方案2】:

    使用对象实现所需行为的略有不同的方法。为了获得真正通用的解决方案,我们需要使用Interfaces。 拆解数据和操作,即分开存放。

    //Interface which describes any kind of data.
    struct IData
    {
            virtual ~IData()
            {
            }
    };
    
    //Interface which desribes any kind of operation
    struct IOperation
    {
            //actual operation which will be performed
            virtual IData* Execute(IData *_pData) = 0;
    
            virtual ~IOperation()
            {
            }
    };
    

    现在,每个操作都知道它所处理的数据类型,并且只需要那种数据。

    struct Operation_Add : public IOperation
    {
                //data for operation addition.
                struct Data : public IData
                {
                        int a;
                        int b;
                        int result;
                };
    
                IData* Execute(IData *_pData)
                {
                        //expected data is "Operation_Add::Data_Add"
                        Operation_Add::Data *pData = dynamic_cast<Operation_Add::Data*>(_pData);
                        if(pData == NULL)
                        {
                                return NULL;
                        }
    
                        pData->result = pData->a + pData->b;
                        return pData;
                }
    };
    
    struct Operation_Avg : public IOperation
    {
                //data for operation average of numbers.
                struct Data : public IData
                {
                        int a[5];
                        int total_numbers;
                        float result;
                };
    
                IData* Execute(IData *_pData)
                {
                        //expected data is "Operation_Avg::Data_Avg"
                        Operation_Avg::Data *pData = dynamic_cast<Operation_Avg::Data*>(_pData);
                        if(pData == NULL)
                        {
                                return NULL;
                        }
    
                        pData->result = 0.0f;
                        for(int i = 0; i < pData->total_numbers; ++i)
                        {
                                pData->result += pData->a[i];
                        }
                        pData->result /= pData->total_numbers;
                        return pData;
                }
    };
    

    这里是运算处理器,CPU。

    struct CPU
    {
                enum OPERATION
                {
                        ADDITION = 0,
                        AVERAGE
                };
    
                Operation_Add m_stAdditionOperation;
                Operation_Avg m_stAverageOperation;
                map<CPU::OPERATION, IOperation*> Operation;
    
                CPU()
                {
                        Operation[CPU::ADDITION] = &m_stAdditionOperation;
                        Operation[CPU::AVERAGE] = &m_stAverageOperation;
                }
    };
    

    示例:

        CPU g_oCPU;
    
        Operation_Add::Data stAdditionData;
        stAdditionData.a = 10;
        stAdditionData.b = 20;
    
        Operation_Avg::Data stAverageData;
        stAverageData.total_numbers = 5;
        for(int i = 0; i < stAverageData.total_numbers; ++i)
        {
                stAverageData.a[i] = i*10;
        }
    
        Operation_Add::Data *pResultAdd = dynamic_cast<Operation_Add::Data*>(g_oCPU.Operation[CPU::ADDITION]->Execute(&stAdditionData));
        if(pResultAdd != NULL)
        {
                printf("add = %d\n", pResultAdd->result);
        }
    
        Operation_Avg::Data *pResultAvg = dynamic_cast<Operation_Avg::Data*>(g_oCPU.Operation[CPU::AVERAGE]->Execute(&stAverageData));
        if(pResultAvg != NULL)
        {
                printf("avg = %f\n", pResultAvg->result);
        }
    

    【讨论】:

      【解决方案3】:

      如果你有以下功能

      int f1(int i);
      int f2(int i, int j);
      

      你可以像这样定义一个泛型函数类型

      typedef int (*generic_fp)(void);
      

      然后初始化你的函数数组

      generic_fp func_arr[2] = {
          (generic_fp) f1,
          (generic_fp) f2
      };
      

      但是你必须把函数转换回去

      int result_f1 = ((f1) func_arr[0]) (2);
      int result_f2 = ((f2) func_arr[1]) (1, 2);
      

      显然,它看起来不是构建程序的好方法

      为了让代码看起来更好一点,你可以定义宏

      #define F1(f, p1) ((f1)(f))(p1)
      #define F2(f, p1, p2) ((f2)(f))(p1, p2)
      
      int result_f1 = F1(func_arr[0], 2);
      int result_f2 = F2(func_arr[1], 1, 2);
      

      编辑

      忘了说,你还必须为每种类型的函数定义一个类型

      typedef int (*fi)(int); // type for function of one int param
      typedef int (*fii)(int, int); // type for function of two int params
      

      然后将存储的指针转换为这些类型

      int result_f1 = ((fi) func_arr[0]) (2);
      int result_f2 = ((fii) func_arr[1]) (1, 2);
      

      这是一个完整的例子

      #include <iostream>
      
      typedef int (*generic_fp)(void);
      typedef int (*fi)(int); // type for function of one int param
      typedef int (*fii)(int, int); // type for function of two int params
      
      #define F1(f, p1) ((fi)(f))(p1)
      #define F2(f, p1, p2) ((fii)(f))(p1, p2)
      
      int f1(int i);
      int f2(int i, int j);
      
      int main()
      {
      
          generic_fp func_arr[2] = {
              (generic_fp) f1,
              (generic_fp) f2
          };
      
          int result_f1_no_macro = ((fi) func_arr[0]) (2);
          int result_f2_no_macro = ((fii) func_arr[1]) (1, 2);
      
      
          int result_f1_macro = F1(func_arr[0], 2);
          int result_f2_macro = F2(func_arr[1], 1, 2);
      
          std::cout << result_f1_no_macro << ", " << result_f2_no_macro << std::endl;
          std::cout << result_f1_macro << ", " << result_f2_macro << std::endl;
      
          return 0;
      }
      
      int f1(int i)
      {
          return i * 2;
      }
      
      int f2(int i, int j)
      {
          return i + j;
      }
      

      上面的代码产生以下输出

      4, 3
      4, 3
      

      【讨论】:

      • 这一行出现错误 int result_f1 = ((f1) func_arr[0]) (2); int result_f2 = ((f2) func_arr[1]) (1, 2);
      猜你喜欢
      • 1970-01-01
      • 2017-03-26
      • 2013-05-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-12
      • 1970-01-01
      • 2016-09-13
      相关资源
      最近更新 更多