C函数声明符
首先,有C。在C中,A a()
是函数声明。例如,putchar
具有以下声明。通常,这样的声明存储在头文件中,但是,如果您知道函数的声明是什么样的,那么没有什么阻止您手动编写它们。参数名称在声明中是可选的,因此在此示例中将其省略。
int putchar(int);
这使您可以编写如下代码。
int puts(const char *);
int main() {
puts("Hello, world!");
}
C还允许您定义具有函数作为参数的函数,并具有良好的可读语法,看起来像函数调用(好吧,只要您不返回函数指针,它就是可读的)。
#include <stdio.h>
int eighty_four() {
return 84;
}
int output_result(int callback()) {
printf("Returned: %d\n", callback());
return 0;
}
int main() {
return output_result(eighty_four);
}
如前所述,C允许省略头文件中的参数名,因此头文件中的参数名output_result
看起来像这样。
int output_result(int());
构造函数中的一个参数
你不认识那个吗?好吧,让我提醒你。
A a(B());
是的,这是完全相同的函数声明。A
是int
,a
是output_result
,B
是int
。
通过C ++的新功能,您可以轻松地注意到C的冲突。确切地说,构造函数是类名和括号,并带有()
代替的替代声明语法=
。根据设计,C ++试图与C代码兼容,因此它必须处理这种情况-即使实际上没有人在乎。因此,旧的C功能比新的C ++功能具有优先权。声明的语法会尝试将名称与函数匹配,然后在()
失败时返回到新语法。
如果这些功能之一不存在,或具有不同的语法(例如{}
在C ++ 11中),则对于带有一个参数的语法将永远不会发生此问题。
现在您可能会问为什么A a((B()))
有效。好吧,让我们output_result
用无用的括号声明。
int output_result((int()));
它不会工作。语法要求变量不能放在括号中。
<stdin>:1:19: error: expected declaration specifiers or ‘...’ before ‘(’ token
但是,C ++希望在这里使用标准表达式。在C ++中,您可以编写以下代码。
int value = int();
和下面的代码。
int value = ((((int()))));
C ++期望括号内的表达式是...表达式,而不是C期望的类型。括号在这里没有任何意义。但是,通过插入无用的括号,将不匹配C函数声明,并且可以正确地匹配新语法(它只需要一个表达式,例如2 + 2
)。
构造函数中的更多参数
当然,一个论点很好,但是两个论点呢?并不是说构造函数可能只有一个参数。带有两个参数的内置类之一是std::string
std::string hundred_dots(100, '.');
一切都很好(从技术上讲,如果将其编写为std::string wat(int(), char())
,则将具有最令人烦恼的解析,但是老实说-谁来写?但是让我们假设这段代码有令人烦恼的问题。您将不得不把括号中的所有内容。
std::string hundred_dots((100, '.'));
并非如此。
<stdin>:2:36: error: invalid conversion from ‘char’ to ‘const char*’ [-fpermissive]
In file included from /usr/include/c++/4.8/string:53:0,
from <stdin>:1:
/usr/include/c++/4.8/bits/basic_string.tcc:212:5: error: initializing argument 1 of ‘std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’ [-fpermissive]
basic_string<_CharT, _Traits, _Alloc>::
^
我不确定为什么g ++尝试转换char
为const char *
。无论哪种方式,都只用type的一个值调用构造函数char
。没有一个类型为的参数的重载char
,因此编译器感到困惑。您可能会问-为什么参数为char类型?
(100, '.')
是的,,
这里是一个逗号运算符。逗号运算符采用两个参数,并给出右侧参数。它并不是真正有用,但是我的解释值得我们了解。
相反,要解决最烦人的解析,需要以下代码。
std::string hundred_dots((100), ('.'));
参数在括号中,而不是整个表达式。实际上,只需在括号中添加一个表达式即可,因为使用C ++功能足以打破C语法就足够了。事情使我们到了零争论的地步。
构造函数中的零参数
您可能已经eighty_four
在我的解释中注意到了该功能。
int eighty_four();
是的,这也受到最烦人的解析的影响。这是一个有效的定义,如果创建了头文件,您很可能已经看到了(应该)。添加括号不能解决问题。
int eighty_four(());
为什么呢?好吧,()
不是表达。在C ++中,必须将表达式放在括号之间。您不能用auto value = ()
C ++ 编写代码,因为()
它没有任何意义(即使那样,如空元组(请参阅Python),它也将是一个参数,而不是零)。实际上,这意味着您不使用C ++ 11 {}
语法就不能使用速记语法,因为括号中没有表达式,并且函数声明的C语法将始终适用。
(B())
只是一个C ++表达式,仅此而已。这不是任何例外。它唯一的区别是不可能将它解析为类型,因此不是。