为什么会这样编译?
int main() {
void f();
}
是什么f
?它是函数还是变量,我该如何使用它?
你有一个函数声明。在块作用域内声明函数是可以的。在块中定义函数是不可能的。仅在本地声明一个函数是非常好的,例如,当您想引用其他一些现有函数时:
int main()
{
int foo();
return foo();
}
您只需将其与一些定义int foo();
.
(这样做可能不是很好的做法,因为它隐藏了您的代码对另一个函数的依赖关系,如果不仔细阅读代码,几乎不可能看到。)
请注意,本地声明隐藏了函数的其他重载,因此参数查找可能与您在全局范围内声明函数时不同。请参阅@David Rodríguez 的更详细的答案。
这是与 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)
似乎是 match ::f(int)
,但本地声明隐藏了重载并::f(double)
作为唯一的解决方案留下,并且在将值转换为 a 后使用重载double
。在 内部main
,局部声明禁用了参数依赖查找,并强制使用::g(int)
,为此对象x
转换为int
.
如果没有本地函数声明,代码将分别调用f(int)
和::A::g(::A::B const&)
,这是大多数开发人员所期望的。
在功能块中声明一个功能是完全可以的。但是在功能块中定义它时会出错。
int main()
{
void func(); //fine
void func() { } //error
}
您不能在另一个函数内 定义/创建一个函数,但您可以在另一个函数内声明一个函数。
int main()
{
void foo(); //ok
void foo() {
} //error
}
允许函数声明,不允许函数定义。
但是,以下是定义明确的代码:
#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();
}
f 是返回类型为 void 的函数的标识符(名称),这里的函数只是在 main 函数中调用才能使用它,你必须声明和定义它这里是语法
void f(); //before main function declaration
int main() //main
{}
void f(); //define here the function f.
最后但并非最不重要的一点是,当且仅当您首先声明和定义它时,您才能使用(调用函数来做一些有用的工作)这个函数。