来自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
这条规则的动机是什么?它似乎限制了函数typedef的潜在表达用途。
答案 0 :(得分:12)
虽然这个问题是关于C ++的,但由于C ++从C继承了typedef
和函数指针,因此可以在这里使用C中相同问题的解释。对C有一个正式的解释。
Rationale for International Standard - Programming Languages C§6.9.1函数定义
参数列表必须显式出现在声明符中;它不能从
typedef
继承(参见§6.7.5.3)。也就是说,给定定义:typedef int p(int q, int r);
以下片段无效:
p funk // weird { return q + r ; }
某些当前实现重写了一个
char
参数的类型,就像它被声明为int
一样,因为已知该参数在缺席时作为int
传递一个原型。但是,标准要求将收到的参数转换为就像在函数输入时的赋值一样。因此不再允许类型重写。
答案 1 :(得分:7)
这可能主要是历史原因。 typedef
是C的相对较晚的补充,并且被添加到现有语言中(并且在编译器的解析阶段引起了一些问题)。
此外,函数定义必须定义参数的名称(如果有)。函数类型包括函数的返回类型和参数类型,但不包括其参数名称。例如,这些:
void (int)
void (int x)
void (int y)
是编写相同函数类型的三种方法。如果你有:
typedef void func_t(int);
那么这个假设的定义:
func_t some_func { }
不会为其int
参数定义名称。我不确定如何以合理的方式解决这个问题。我想,这是可能的,但它从未完成。
但最重要的可能就是Dennis Ritchie要么不认为定义如何在函数定义中使用typedef
,或者他根本没有想到它。
答案 2 :(得分:1)
让我说几句话。考虑一个声明:
typedef void F(int p1, char* p2);
此语句将名称F
分配给函数签名void (int, char*);
这是函数签名的别名的定义。在那之后声明:
F fv;
告诉我有一个函数fv
。它有上面提到的签名,它的身体在某处。查看函数定义的C / C ++语法:
retType funcName(params) { body }
实际上有2个名称使用retType
和funcName
。它们都与初始typedef中的名称F
无关。名称F
具有两个名称的含义。如果语言允许这样的话:
F { body }
这会将body与函数类型相关联。但这导致了一个问题:
F
的含义不明确。它是“函数签名的别名”还是“代码入口点的名称”?
另外,最后一个例子的语法对数百万C / C ++程序员来说很奇怪。
答案 3 :(得分:-4)
规则与您引用的一样 - typedef of function type shall not be used to define a function
。在示例的第3行中,您尝试定义函数类型为F
的函数。标准不允许这样做。
修改强>
正如你所指出的那样,我试着解释一下它。
对于第3行,如果它是合法的,那么你可以用typedef定义替换F:
void fv { }()
。这不是C ++中的合法定义或声明。
我认为关键点是typedef
只是为简化创建了一个别名,你可以在编译期间替换你的typedef类型,如替换#define
。