职能的宣言和实施

时间:2010-12-08 19:06:42

标签: c++ implementation user-defined-functions

根据我的老师的说法,编写这样的用户定义函数是不好的做法:

int DoubleNumber(int Number)
{
    return Number * 2;
}

int main()
{
    cout << DoubleNumber(8);
}

相反,他说总是使用前向声明,即使这些函数不需要彼此了解:

int DoubleNumber(int Number); // Forward declaration.

int main()
{
    cout << DoubleNumber(8);
}

int DoubleNumber(int Number) // Implementation.
{
    return Number * 2;
}

我觉得这特别奇怪,因为他告诉我们前向声明和实现完全相同或者你会得到错误是多么重要。如果它是如此重要,为什么不把它全部放在main()之上?

那么,同时申报和实施真的是不好的做法吗?它甚至重要吗?

9 个答案:

答案 0 :(得分:13)

如果您没有声明前向声明(“prototypes”),那么您需要确保所有函数在依赖于它们的任何函数之前发生,即以调用图的相反顺序。这对于上面的一个简单示例来说很好,但对于任何更现实的事情来说都是完全痛苦的(如果调用图中有任何循环,在某些情况下是不可能的)。

答案 1 :(得分:6)

你的老师的政策是可怕的恕我直言。只有在真正需要时才使用前向声明。这样,它们的存在证明了它们的必要性,这给读者提供了有用的文档(即,函数之间可能存在相互递归)。当然,你需要头文件中的前向声明;这就是他们的目的。

答案 2 :(得分:6)

我认为你的老师是一位老C程序员。

如果你编写了一个没有前向声明的C程序和一个稍后在文件中声明的另一个函数(或者在不同的编译单元中),编译器就不会抱怨,而是默默地假装知道原型应该是什么。

如果您不知道编译器是否正确传递了参数,那么调试很糟糕。因此,始终宣布所有职能是一个很好的防御政策;如果声明与实现不匹配,至少编译器可能会引发错误。

C编译器和工具变得更好(我希望)。调用未知函数仍然不是错误,但例如GCC就足以在默认情况下发出警告。

但在C ++中,您无法调用尚未声明或定义的函数。因此,C ++程序员并不担心前向声明。

答案 3 :(得分:4)

在我的第一个编程课上,老师也强调了这一点。我不确定在实际软件中这样一个简单的案例是否有好处。

但是,确实准备使用头文件,如果还没有涵盖那么。在典型情况下,您将拥有头文件custom-math.h和源文件custom-math.cpp,其中custom-math.h包含前向声明和custom-math.cpp实现。如果仅在大型项目中对函数实现进行修改,这样做可能会显着增加编译时间。它也是将程序拆分为“逻辑”功能和/或类组的便捷方式。

如果 要将其他功能放在与main()相同的文件中,那么您所做的可能取决于您的个人偏好。有些人喜欢让main()靠近顶部以立即进入程序逻辑。在这种情况下,转发声明你的功能。

答案 4 :(得分:3)

Karl Knecthel写道“只有在真正需要时才使用前向声明。这样,他们的存在就证明了它们的必要性,这为读者提供了有用的文档(即,函数之间可能存在相互递归)。”和恕我直言,这是合理的建议。

Oli Charlesworth谈到订购函数的“完全痛苦”,以便可以在没有前向声明的情况下调用它们。那不是我的经验,我无法想象这种痛苦/问题是如何实现的。我怀疑那里有一个PEBCAK问题。

对所有函数使用前向声明的做法不会使您免于PEBCAK问题,但是它们确实引入了不必要的维护工作和不必要的更多代码来关联,并且它们确实使得更加不清楚哪些函数确实需要前向声明。 / p>

如果到达前向声明有助于一目了然地看到函数签名的点,当被迫使用一些非常简单的编辑器时,则应该采取两种操作:(1)重构代码,以及( 2)切换到更好的编辑器。

干杯&amp;第h。,

答案 5 :(得分:2)

向你的老师询问为什么他推荐这个;)无论如何,在我看来这并不坏,在大多数情况下它甚至都不重要。预先声明所有功能的最大优点是,您可以高度概述代码的功能。

答案 6 :(得分:1)

传统上你会将所有原型都粘贴在头文件中,因此它们可以被其他源文件使用 - 或者至少,你将把想要公开的那些放在.h文件中。

对于没有必要的代码,可以说将所有文件级声明放在顶部(变量和函数),因为这意味着你可以随意移动函数而不必担心它。更不用说,我可以立即看到文件中的每个功能。但是类似的东西:

void Func1() { ... }
...
void Func2() { ... }
...
void Func3() { ... }
...
int main() { Func1(); Func2(); Func3(); return 0; }

那 - 也就是说,main()调用的一些脱节函数是一个非常常见的文件,放弃声明是完全合理的。

答案 7 :(得分:1)

一揽子规则很少正确。您通常会通过头文件中的原型公开公共API。其余的函数可能位于cpp文件中的匿名名称空间中。如果在实现中多次调用它们,那么在顶部提供原型是有意义的,否则使用它们的每个函数都必须在调用函数之前提供原型。同时,如果在cpp文件中多次使用某些函数,则可能表明它已经足够通用以移动到公共API。如果没有在所有地方使用这些功能,最好尽可能多地提供它们,即在它们被调用的地方附近声明和定义它们。

答案 8 :(得分:0)

就个人而言,我只想转发声明客户端代码需要的任何内容(即在类头中)。应该在使用之前定义类实现的本地任何内容(例如辅助函数)。

当然,在一天结束时,在很大程度上,它归结为您的项目所遵循的个人偏好或编码标准。