来自ISO/IEC 14882:2011(E)第8.3.5.11节:
函数类型的typedef可以用于声明函数,但不得用于定义函数。
标准继续给出了以下示例:
typedef void F();
F fv; // OK: equivalent to void fv();
F fv { } // ill-formed
void fv() { } // OK: definition of fv
这个规则的动机是什么?它似乎限制了函数类型定义的表达上的潜在用途。
来自ISO/IEC 14882:2011(E)第8.3.5.11节:
函数类型的typedef可以用于声明函数,但不得用于定义函数。
标准继续给出了以下示例:
typedef void F();
F fv; // OK: equivalent to void fv();
F fv { } // ill-formed
void fv() { } // OK: definition of fv
这个规则的动机是什么?它似乎限制了函数类型定义的表达上的潜在用途。
虽然这个问题是关于C++的,但由于C++从C中继承了typedef
和函数指针,因此可以使用C中相同问题的解释。在C中有一个正式的解释。
国际标准的理由 - 编程语言C §6.9.1 函数定义
参数列表必须在声明符中显式地存在;它不能从
typedef
中继承(参见§6.7.5.3)。也就是说,给定以下定义:以下片段无效:
typedef int p(int q, int r);
the following fragment is invalid:
以下代码片段无效:以下代码片段无效:
p funk // weird { return q + r ; }
目前有些实现会将一个
char
类型的参数重写为int
类型,因为在没有原型的情况下,已知该参数作为int
类型传递。然而,标准要求函数在进入时将接收到的参数像赋值一样进行转换。因此,不再允许进行类型重写。
这可能主要是历史原因。 typedef
是相对较晚加入 C 语言的,并且被附加到现有的语言上(并为编译器的解析阶段带来了一些问题)。
此外,函数定义必须定义参数的名称(如果有)。函数类型包括函数的返回类型和参数类型,但不包括其参数名称。例如:
void (int)
void (int x)
void (int y)
typedef void func_t(int);
func_t some_func { }
该函数没有为其int
参数定义名称。我不确定如何以合理的方式解决这个问题。我想这是可能的,但从未实现过。
但最重要的是,Dennis Ritchie可能认为定义如何在函数定义中使用typedef
不值得花费精力,或者他根本没有想到。
void some_func(int) { }
相同。 - Benjamin Lindleytypedef
定义的任何函数都不能有命名参数。这将是一个令人烦恼和武断的限制。没有能力将其推广,允许一个特殊情况是不值得的。在C语言中,typedef起源的地方,函数定义中不允许无名称的参数。 - Keith ThompsonLet me put a few words. Consider a statement:
typedef void F(int p1, char* p2);
F
赋值给函数签名void (int, char*)
。这是一个函数签名的别名定义。随后的语句:F fv;
这段文字表明存在一个名为fv
的函数。它具有上述提到的签名并且其函数体位于某处。请查看该函数定义的C/C++语法:
retType funcName(params) { body }
retType
和 funcName
。它们都和最初的 typedef 中的名字 F
不同。名字 F
包含了这两个名字的意义。如果语言允许像下面这样的东西:F { body }
typedef 函数类型不应该用于定义函数
。在示例的第三行,你试图使用函数类型F
来定义一个函数。这是标准不允许的。
编辑
正如你所指出的,我会更详细地解释一下。
对于第三行,如果它是合法的,那么您可以使用typedef定义来替换F:
void fv { }()
。 这不是C ++中的合法定义或声明。
我认为关键点在于,typedef
只是为了简化而创建一个别名,并且您可以在编译期间像#define
替换一样替换typedef类型。
F fv { }
就是有效的。 - Keith Thompsonv {}
视为一个整体。将其集成到 typedef 中,它将变成 **void fv {}()**。这怎么合法呢? - Zachary
typedef
为另一个类型创建了一个别名,这在你的情况下是一个函数类型。对于第三个(不良形式)的示例,F
是指函数的返回类型还是函数本身的类型? - Mark Garcia