为什么要编译?
int main() {
void f();
}
什么是f
?它是一个函数还是一个变量,我该如何使用它?
答案 0 :(得分:6)
你有一个功能声明。在块范围内声明函数是可以的。在块中定义函数是不可能的。仅在本地声明一个函数是完全正常的,例如,当你想引用其他一些现有的功能时:
int main()
{
int foo();
return foo();
}
您只需将其与定义int foo();
的某个翻译单元相关联。
(这可能不是很好 practice 这样做,因为它隐藏了代码对其他函数的依赖性,这种方式几乎不可能在没有仔细阅读代码的情况下看到。)
请注意,本地声明隐藏了函数的其他重载,因此参数查找可能与您在全局范围内声明函数的情况不同。请参阅@DavidRodríguez的更详细的答案。
答案 1 :(得分:5)
这是C的旧向后兼容功能,它允许范围内的函数的声明(函数级别或函数内的范围)。 C中的效果非常简单,它提供了等效的常规函数声明,但名称只在此作用域内可见,因此编译器不需要在当前作用域之外关注它。
在C ++中,事情有点复杂。拥有名称空间需要更复杂的查找规则,过载需要重载解析。在该标准的某些早期版本中,接受了本地函数声明应该隐藏任何其他函数声明的相同名称(这与一般的查找一致),并禁用参数依赖查找。毕竟,如果用户声明它如此接近使用,她必须要调用此函数。一段时间后,有人试图从语言中完全删除该功能,但是希望为现有客户端代码库支持它的供应商面临这种情况。
这会直接影响哪些函数重载是可见的,而这又会影响被调用的内容。这是危险的,因为大多数人不知道查找差异,应该避免。这意味着什么的一些例子:
namespace A {
struct B {
operator int();
};
void g(B const&);
}
void f(int);
void f(double);
void g(int) {
void f(double);
f(1); // calls f(double)
}
int main() {
void g(int);
A::B x;
g(x); // calls g(static_cast<int>(x))
}
在g(int)
内,调用f(1)
似乎与::f(int)
匹配,但是本地声明会隐藏该重载,并将::f(double)
作为解析的唯一候选者,并且将值转换为double
后使用重载。在main
内,本地声明禁用参数相关查找,并强制使用::g(int)
,对象x
将转换为int
。
如果没有本地函数声明,代码将分别调用f(int)
和::A::g(::A::B const&)
,这正是大多数开发人员所期望的。
答案 2 :(得分:2)
在功能块中声明一个函数是完全正确的。但是在功能块中定义它时会出错。
int main()
{
void func(); //fine
void func() { } //error
}
答案 3 :(得分:2)
您无法 在另一个函数中定义/创建一个函数,但 可以声明 一个函数在另一个功能中。
int main()
{
void foo(); //ok
void foo() {
} //error
}
答案 4 :(得分:1)
允许使用函数声明,而不是函数定义。
但是,以下是明确定义的代码:
#include <iostream>
int main()
{
// void function() {}; // a function-definition is not allowed
struct Function {
static void apply() {
std::cout << "Hello World" << std::endl;
}
};
Function::apply();
}
答案 5 :(得分:0)
f是返回类型为void的函数的标识符(name),这里函数只是在main函数中调用才能使用它,你必须在这里声明和定义它是语法
void f(); //before main function declaration
int main() //main
{}
void f(); //define here the function f.
当且仅当你首先声明并定义它时,最后但并非最不重要的是你可以使用(调用函数做一些有用的工作)这个函数。