声明类型为 void C++ 的函数数组

Declaring an array of functions of type void C++

我有一些 return void 的功能。我指向这些函数并希望得到这些函数的数组:

此代码为何有效:

#include <cstdio>
using std::puts;

void tell() {
  puts("hi");
};

void slap() {
  puts("goodbye");
}

int main(int argc, char *argv[])
{

  void (*tp)() = tell;
  void (*sp)() = slap;

  void(*funcs[])() = {tp, sp};
  for (auto point:funcs) {
    point();
  }
  return 0;
}

当我在 funcs(即 void(funcs[])() = {tp, sp}; 中没有指定指针的情况下尝试此代码时,我得到 " error: 'funcs' declared as array of functions of type 'void ()' " 这正是它们的含义 - 那么为什么会出现错误?

我也不懂语法,void(*funcs[])()末尾的()不是表示实际调用函数吗?

C++ 标准 8.3.5/10 说:

There shall be no arrays of functions, although there can be arrays of pointers to functions.

必须使用 "spiral rule":

读取“funcs”的声明

funcs[]: funcs 是一个数组

*funcs[]: funcs 是一个指针数组

(*funcs[])(): funcs 是指向无参数函数的指针数组

void (*funcs[])(): funcs 是指向函数的指针数组,不带参数返回 void.

没有星号,void (funcs[])() 声明一个函数数组而不是 指针数组 函数。后者在 C++ 语法中是允许的,而前者是不允许的。

[dcl.array]/p1:

T is called the array element type; this type shall not be a reference type, the (possibly cv-qualified) type void, a function type or an abstract class type.

初始化列表 ({tp, sp}) 的内容是函数,但它们通过函数到指针的转换被转换为指针:

[conv.func]/p1

An lvalue of function type T can be converted to a prvalue of type “pointer to T.” The result is a pointer to the function.

请注意,C++ 也不允许引用数组。


I also don't get the syntax, wouldn't the () at the end of void(*funcs[])() indicate actually calling a function?

不是,这是数组类型的声明。 () 是指定函数参数列表的类型构造的一部分。整个类型表示"an array of pointers to functions which take zero arguments (()) and return void"。使用类型别名可能会变得更清楚:

using void_f = void (*)();
void_f funcs[] = {tp, sp};

这样使用:

int main(int argc, char *argv[])
{
    void (*tp)() = tell;
    void (*sp)() = slap;

    void (*funcs[])() = {tp, sp};
    for (void (*point)():funcs)
    {
        point;
    }
    return 0;
}

好吧,你可以像这样明确地声明它:

void (*actions[5])();

但这几乎不可读。
为了使其更具可读性,请使用 typedef。

typedef void(*Action)();    // Action is the typename for a pointer
                            // to a function return null and taking
                            // no parameters.

Action   actions[5];        // An array of 5 Action objects.

或者为了您的目的:

int main()
{
     Action   actions[] = {&tell, &slap};
}