C++中未命名函数指针的语法

14

我正在研究最棘手的解析问题,然后我偶然发现了类似这样的东西:

Foo bar(Baz()); // bar is a function that takes a pointer to a function that returns a Baz and returns a Foo

这与 return-type(*name)(parameters) 的典型语法非常不同。这些括号是参数列表的括号,还是名称的括号?


1
哦,我的C++,语法有时候真的很令人困惑。如果Baz是一个不带参数返回Foo的函数,那么这将声明bar为类型为Foo的变量,并初始化为Baz()。但是如果Baz是一个类型,则bar被声明为函数?!太疯狂了... - Ray Toal
2
@RayToal 对不起自我推销,但您可能会喜欢我去年整理的这个解析滥用 ;) - Quentin
自我推广受欢迎! - Ray Toal
3个回答

17

完整显式形式:

Foo bar(Baz f());

bar 是一个接受单个参数 f 的函数,这个参数是一个不带参数但返回 Baz 类型的函数。

不给参数命名:


Foo bar(Baz ());

bar 最终成为一个函数指针的原因是函数无法通过值传递,因此将参数声明为函数会自动将其转换为指针。上面的声明等效于:

Foo bar(Baz (*)());

// or:
Foo bar(Baz (*f)());  // with a named parameter

这类似于 void foo(int [10]),其中 int [10] 在参数列表中也意味着 int *


是否应该使用一种语法而不是另一种(忽略std :: function的使用)?如果我要将函数指针作为参数,我应该编写普通函数声明并让它衰减为指针,还是应该直接编写函数指针声明? - Krystian S
3
这是个人口味问题。我更喜欢显式表达,所以当我的参数是指针时,我会将它们声明为指针(而不是数组或函数)。 - melpomene
为了大家的健康,您应该提前定义一个别名并在参数列表中使用它。 - Sebastian Redl

6
声明中有两组括号。外部括号是函数 bar 的参数列表:
Foo bar(Baz());
       ^     ^

在这个声明中,Baz() 是一个函数类型。函数类型声明中的括号限定了该函数的参数列表。
Foo bar(Baz());
           ^^

澄清一下:在函数参数声明符的上下文中,函数类型被调整为该类型的一个函数指针。因此,声明实际上等同于:

Foo bar(Baz(*)());
           ^ ^

这个备选指针参数声明符的括号是在“预调整”声明中不存在的。
相关的标准规则:
[dcl.fct]
使用以下规则确定函数的类型。每个参数(包括函数参数包)的类型都是从其自身的decl-specifier-seq和declarator中确定的。在确定了每个参数的类型之后,任何类型为“T数组”或函数类型T的参数都被调整为“指向T的指针”。...

3
这个括号是用来表示参数列表的,还是表示名称的呢?
它们是用来表示参数列表的。
因此:
Foo bar(Baz());

声明一个接受单个参数的函数,该参数是一种返回Baz且不接受参数的函数类型。

这等同于一个函数声明,该函数接受单个参数,该参数是一个返回Baz且不接受参数的函数指针类型(来自函数):

根据以下规则确定参数列表中每个函数参数的类型:

...

3) 如果类型是函数类型 F,则用“指向 F 的指针”类型替换它

...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接