我曾是 阅读 导致我问这个问题的链接问题。

考虑下面的代码

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;
}

与许多 C 约定一样,这是 C++ 所采用的约定。

在 C 语言中,在另一个函数中声明一个函数的能力是大多数程序员可能认为令人遗憾和不必要的决定。特别是在现代 OOP 设计中,函数定义比 C 中的要小。

如果您希望函数仅存在于另一个函数的范围内,有两个选项: 升压::拉姆达C++1x 拉姆达.

至于为什么你的声明

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
   ...
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top