不允许嵌套函数,但为什么允许嵌套函数原型?[C++]
-
06-09-2019 - |
题
我曾是 阅读 导致我问这个问题的链接问题。
考虑下面的代码
int main()
{
string SomeString();
}
总而言之,编译器将其视为函数原型而不是 细绳 目的。现在考虑以下代码。
int main()
{
string Some()
{
return "";
}
}
编译器说这是无效的,因为我猜嵌套函数定义是不允许的。 如果不允许,为什么允许嵌套函数原型? 它没有提供任何优势而不是造成混乱(或者我在这里遗漏了一些有效的观点?)。
我发现以下内容是有效的。
int main()
{
string SomeFun();
SomeFun();
return 0;
}
string SomeFun()
{
std::cout << "WOW this is unexpected" << std::endl;
}
这也令人困惑。我期待这个功能 一些乐趣() 范围仅在 主要的. 。但是我错了。为什么编译器允许编译上面这样的代码?在任何实时情况下,上面的代码是否有意义?
有什么想法吗?
解决方案
您的原型就是 '正向的宣言'。请看看维基百科的文章。
基本上,它告诉编译器“如果标签‘SomeFun’以这种方式使用,不要惊慌。” 但是你的连接器是何等的负责查找正确的函数体。
可以实际声明一个伪造原型,例如“字符SomeFun()”,并用它在你的主。当你的连接试图找到自己的虚假功能的身体,你只会得到一个错误。但是,你的编译器会凉着了。
有很多的好处。你要记住函数体并不总是相同的源代码文件。它可以是一个链接library.Also,该链接库可能是有一个特定的“链接signature'.Use有条件的定义,你甚至可以使用您的作用域prototypes.Although大多数人会使用函数指针选择在构建时正确的链接签名该代替。
希望这有助于。
其他提示
正如一个方面说明,C ++ 03确实具有限定的局部函数的一个迂回的方式。它需要滥用本地级特征:
int main()
{
struct Local
{
static string Some()
{
return "";
}
};
std::cout << Local::Some() << std::endl;
}
至于为什么你的声明
void f() {
void g(); g();
}
是比这一个
更好void g();
void f() {
g();
}
如果你把声明的地方越好,让尽可能少的名称冲突的可能的结果通常是好现象。我说这是值得商榷是否声明本地函数(这种方式)是的真正的幸运,因为我认为这是最好还是普通包含它的头,然后去“通常”的方式,这也是减少混乱人们不知道这一点。有时,它也是有用的解决被遮挡的功能
void f() {
int g;
// oops, ::g is shadowed. But we can work around that
{
void g(); g();
}
}
当然,在C ++中,我们可以调用使用g
功能its_namespace::g()
- 但在过去的C,这将不会成为可能,而那件事让程序员可以访问这些功能。同时还要注意语法是不一样的,语义以下局部范围内的确也声明一个函数,实际上针对不同的范围。
int main() {
using std::exit;
exit();
}
作为边注,有更多的情况一样,其中声明的目标范围为不其中该声明出现在范围之内。通常,需要声明的实体成为所述一个构件范围在其中出现的声明。但事实并非总是如此。例如,考虑朋友的声明,其中说的事情发生了。
struct X { friend void f() { std::cout << "WoW"; } };
int main() { void f(); f(); } // works!
即使函数声明(和定义!)f
的发生X
的范围之内,所述实体(函数本身)成为封闭命名空间的成员。
函数原型的提示编译器。他们表示该功能被实现在其他地方,如果还没有的发现的。仅此而已。
在声明原型你正在做的,你基本上是告诉编译器等待连接器来解决它。根据你写的作用域规则同样适用原型。没有什么技术上的错误写你的main()函数中的原型(恕我直言,虽然有点混乱),它只是意味着该功能在主里面只有当地人称为()。如果您已声明原型在源文件的顶部(或在头文件中更常见),原型/功能将整个源已知的。
string foo()
{
string ret = someString(); // Error
return ret;
}
int main(int argc,char**argv)
{
string someString();
string s = somestring(); // OK
...
}