【问题标题】:How can a function pointer replace switch statement?函数指针如何替换 switch 语句?
【发布时间】:2014-10-16 06:06:27
【问题描述】:

我正在阅读有关函数指针的教程,它说函数指针可以替换 switch 语句 http://www.newty.de/fpt/intro.html

谁能澄清一下?

我们有一个这样的 switch 语句:

// The four arithmetic operations ... one of these functions is selected
// at runtime with a swicth or a function pointer
float Plus    (float a, float b) { return a+b; }
float Minus   (float a, float b) { return a-b; }
float Multiply(float a, float b) { return a*b; }
float Divide  (float a, float b) { return a/b; }


// Solution with a switch-statement - <opCode> specifies which operation to execute
void Switch(float a, float b, char opCode)
{
   float result;

   // execute operation
   switch(opCode)
   {
      case '+' : result = Plus     (a, b); break;
      case '-' : result = Minus    (a, b); break;
      case '*' : result = Multiply (a, b); break;
      case '/' : result = Divide   (a, b); break;
   }

   cout << "Switch: 2+5=" << result << endl;         // display result
}

// Solution with a function pointer - <pt2Func> is a function pointer and points to
// a function which takes two floats and returns a float. The function pointer
// "specifies" which operation shall be executed.
void Switch_With_Function_Pointer(float a, float b, float (*pt2Func)(float, float))
{
   float result = pt2Func(a, b);    // call using function pointer

   cout << "Switch replaced by function pointer: 2-5=";  // display result
   cout << result << endl;
}


// Execute example code
void Replace_A_Switch()
{
   cout << endl << "Executing function 'Replace_A_Switch'" << endl;

   Switch(2, 5, /* '+' specifies function 'Plus' to be executed */ '+');
   Switch_With_Function_Pointer(2, 5, /* pointer to function 'Minus' */ &Minus);
}

如您所见,作为示例的 Replace_A_Switch() 函数非常不清楚。假设我们需要将函数指针指向 4 个算术函数(Plus、Mins、Multiply、Divide)之一。我们怎么知道我们需要指向哪一个?我们必须再次使用switch语句将函数指针指向算术函数,对吧?

会是这样的**(请在代​​码中注释)**:

void Replace_A_Switch()
{
    .....................
    ..........
    //How can we know this will point to the &Minus function if we don't use the switch statement outside?
    Switch_With_Function_Pointer(2, 5, /* pointer to function 'Minus' */ &Minus);
}

所以总结一下,函数指针的优点是什么,总是说函数指针是一种后期绑定机制,但是在本教程中我没有看到函数指针对于后期绑定的任何优势。 非常感谢任何帮助。谢谢。

【问题讨论】:

  • 简而言之,您需要一个函数指针数组,可以按您的操作码类型进行索引。由于您的索引是 char 而不是一些合成字节码,这意味着 256 个元素,请记住将索引转换为 unsigned char
  • 鉴于您使用 C++ 进行编码,为什么不使用带有虚拟方法的类层次结构,让编译器担心这一切的机制?
  • @NPE 因为,虽然抽象很好,但也会导致 VM 速度慢(相对)......这也与探索这种方法的目的背道而驰。
  • 虚函数并不比函数指针快或慢。函数指针就是虚函数。

标签: c++ c pointers function-pointers


【解决方案1】:

你说的很对,你仍然需要在某个地方决定使用什么函数指针。

您正在查看的是一个非常简单、人为的示例,用于解释目的。它展示了如何利用函数指针。在这种情况下,它可能会变得毫无意义地复杂,但实际案例可能太复杂而无法用于指导这个基本概念。

当您拥有许多具有相同开关或具有相同集合子集的开关时,差异会变得更加明显。区别是一样的(这也很重要)。既然如此,何必重写一堆呢?

它还会打开您的代码以更改决策方式。也许您出于某种原因想要反转“+”和“-”。更改您制作指针和所有客户端代码赶上的点。

最后,如果您甚至不需要做出决定怎么办?例如,不更换开关,如果您只想做加法版本怎么办?显然,对于这种级别的设计来说,加法任务太简单了,但这只是一个例子。

无论您使用的是函数指针还是类层次结构,这一切都是正确的。必须有人决定输入是什么。这些结构的作用是为您提供一种将不同位组合到正在运行的程序中的方法。它还将负责决定使用哪个版本的事物与使用这些事物分开的部分。有很多不同的方法来处理这种创建(请参阅创建设计模式了解一些)。

【讨论】:

  • 谢谢,但您能否仅举一个示例或提供此类示例的任何链接
  • 我想 C 回调是遵循函数指针行的真实示例。我想不出一个使用它们的库,我会说它很好用。选择我猜的 C UI API 之一。有 win32、gtk、motif ... 仅举三例。
【解决方案2】:

正如教程所述,没有任何优势,基本计算器只是一个示例。函数指针的主要用途是允许 API-dev 定义一个函数,该函数执行创建 API 时未知的操作。

一个更好的例子可能是qsort,它带有一个比较函数。多亏了这个函数指针参数,才有可能以通用的方式实现排序。由于您不可能知道需要对哪种数据进行排序,因此您无法知道必须如何实现 &lt;,=,&gt; 运算符。因此,您希望调用者提供一个实现比较的函数,从而避免这种困境。

一般来说,如果您想以通用方式进行编程,函数指针通常很有用。它的用途是其他语言中的函数参数。例如,如果有人要求你实现一个简单的 reduce 函数,你可以想出这样的方法:

 void reduce(void *data, size_t nmemb, size_t size,
        void (*op)(void *, void *), void *res){
                int i;
                for (i = 0; i < nmemb; ++i){
                        op(data, res);
                        data = (void *)((unsigned char*)data + size);
                }
        }

显然,对于乘法、加法和更复杂的操作,用相应的函数替换 op 来重写它是非常有利的。

【讨论】:

    【解决方案3】:

    我可以看到如何将“+”、“-”等转换为 enum,并将 4 个 func 指针存储到按 enum 顺序排序的数组中。之后arr[op]就是你想要的函数,执行即可。

    或者std::map&lt;String, FuncType&gt; 映射来自+ -> &amp;Plus

    【讨论】:

      【解决方案4】:

      据我所知..

      pt2Func 是为引用函数的指针定义的名称

      您可以在调用它的主目录中看到它是如何工作的 (删除评论使其更具可读性)

      Switch_With_Function_Pointer(2, 5, &Minus);
      

      &Minus 这里是一个指向你的函数 Minus

      的指针

      这很愚蠢,因为您正在调用一个函数来使用指针引用另一个函数。 没有任何好处,也没有什么特别之处。它只是调用 Minus 函数的另一种更复杂的方法

      Switch 函数只是一个普通的开关,封装在一个函数中以实现可重用性

      【讨论】:

        猜你喜欢
        • 2021-12-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-10
        • 1970-01-01
        相关资源
        最近更新 更多