【问题标题】:using typedef to wrap functions使用 typedef 包装函数
【发布时间】:2012-11-12 18:13:22
【问题描述】:

我的一位老师使用这种类型声明:

typedef void (*SortFunction)(int a[], int n);

创建一个可以保存指向函数的指针的类型 并且可以用于稍后在程序中调用该函数。

我也知道要将函数作为参数传递,您必须 将函数名括在括号中并将函数的 函数名后面括号里的参数也是这样

function someFunction( (anotherfunction)(type arg1, type arg2,...)){
  ...
} 

我想知道的是为什么你必须像这样在括号中包装一个函数?这是大多数 C++ 编译器的内置函数还是我们程序员使用的一个技巧 为了在我们的代码中启用函数作为参数?还有,为什么“SortFunction” typedef语句中需要引用,为什么你用来利用SortFunction的变量不能只持有函数而不是指向它?

【问题讨论】:

    标签: c++ function pointers wrapper typedef


    【解决方案1】:

    函数参数没有什么特别之处。每当你声明一个函数指针(作为局部变量、全局变量、类成员变量、函数参数、typedef等)时,它总是这样声明的:

    return_type (*var_name)(T1 param1, T2 param2, /* etc. */ );
    //           ^
    //           |
    // This * is very important!
    

    其中var_name 是函数指针变量的名称。 *var_name 周围需要括号的原因是由于运算符优先级:没有括号,*(表示某些东西是指针)将与函数的返回类型匹配,而您会得到类似返回类型的东西的int*(指向int)而不是普通的int

    您不能将函数作为参数传递,因为函数不是 C 和 C++ 中的一等对象。传递函数的唯一方法是我传递一个指向函数的指针。

    【讨论】:

      【解决方案2】:

      “我也知道要将函数作为参数传递,你必须将函数名括在括号中......”你“知道”不正确。

      为了将函数指针作为参数传递,您不必将名称括在括号中。例如,这将完全正常

      void foo(int i) {
      } 
      
      void bar(void f(int)) {
        f(5);
      }
      
      int main() {
        bar();
      }
      

      在上面的示例中,函数bar 接收指向函数foo 的指针作为参数,并通过该指针调用foo,并将5 作为参数传递。可以看到,参数声明中的函数名f没有用括号括起来。

      在这种情况下,参数f 的类型实际上是一个指向函数的指针,即使它没有明确声明为指针。在函数参数声明中使用函数类型时,编译器会自动将其隐式“替换”为函数指针类型。

      如果你想显式使用函数指针类型,你必须声明bar

      void bar(void (*f)(int)) {
        f(5);
      }
      

      在这种情况下,(*f) 中的括号是必要的,以确保 * 将绑定到 f 而不是 void。如果没有括号,void *f(int) 声明将代表“函数返回 void *”,而不是所需的“指向函数返回 void 的指针”。

      【讨论】:

        【解决方案3】:

        这是语法问题。您的第一个 typedef 定义了一个类型,该类型是一个接收 int 向量和 int 并且什么都不返回 (void) 的函数。

        SortFunction 类型的变量在概念上将与任何其他变量一样,尽管它指向某个函数。优点是您可以更改它指向的函数和/或动态调用该函数。

        【讨论】:

          【解决方案4】:

          我想知道的是为什么你必须像这样在括号中包装一个函数?

          因为必须有某种方法来识别指向编译器(或者更确切地说,解析器)的函数指针,而这种方法看起来和任何方法一样好。在 C++11 领域,您可以改用:std::function<void(std::array<int>&)>

          这是大多数 c++ 编译器的内置函数,还是我们程序员为了在代码中启用函数作为参数而使用的一种技巧?

          函数指针需要一点额外的魔力,如果没有编译器支持,它们使用起来会非常非常不方便。我也有理由确定,几乎所有程序员的技巧最终都是编译器的功能!

          另外,为什么typedef语句中的“SortFunction”需要被引用,为什么你用来利用SortFunction的变量不能只持有函数而不是指向它?

          嗯。不完全确定你在这里的意思。你的意思是“为什么这需要typedef...为什么我不能在我的函数参数中写出整个函数指针原型”?因为你可以:

          void foo(void(*funcptr)()) {}
          

          如果你的意思是“为什么函数指针必须指向一个函数而不是内联代码”那么你需要 C++11 和 lambdas:

          #include <iostream>
          #include <functional>
          
          void foo(std::function<void(void)> bar) { bar(); }
          
          int main(int argc, char* argv[])
          {
              foo([]() { std::cout << "hi!" << std::endl; });
          }
          

          (同样,lambda 需要特殊语法,[](){},只是为了告诉解析器发生了什么)

          【讨论】:

          • 请注意,如果我阅读了最新的 C++11 标准,上下文无关的 lambda 可以隐式转换为函数指针。
          • @Yakk 你可能是对的,但我必须亲自支持的两个编译器都不支持这一点。然而,两者都没有特别强大的 C++11 支持。
          • 是的——我相信,这是在标准化周期的后期添加的。或者可能没有添加,只是考虑...
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-06-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多