本地函数声明有用吗?

时间:2009-06-23 19:24:35

标签: c++ function definition local

像我这样的大多数C ++程序员在某些方面犯了以下错误:

class C { /*...*/ };

int main() {
  C c();     // declares a function c taking no arguments returning a C,
             // not, as intended by most, an object c of type C initialized
             // using the default constructor.
  c.foo();   // compiler complains here.

  //...
}

现在虽然错误是非常明显的,一旦你知道它我想知道这种本地函数声明是否有任何明智的用途,除了你可以做到 - 特别是因为没有办法定义< / em>同一块中的这种局部函数;你必须在其他地方定义它。

我认为Java风格的本地类是一个非常好的功能,我倾向于经常使用,尤其是匿名排序。甚至本地C ++类(可以具有内联定义的成员函数)也有一些用处。但是这个没有定义的本地函数声明对我来说似乎很尴尬。它只是一个C-legacy还是有一些我不知道的更深层的用例?

非信徒的

编辑C c() 是一个函数指针声明。

这个程序

int main()
{
  void g();
  cout << "Hello ";
  g();
  return 0;
}

void g()
{
  cout << "world." << endl;
}

输出Hello world.此程序

void fun()
{
  cout << "world." << endl;
}

int main()
{
  void g();
  g = fun;
  cout << "Hello ";
  g();
  return 0;
}

无法编译。 gcc抱怨道:

error: cannot convert 'void ()()' to 'void ()()' in assignment

科莫:

error: expression must be a modifiable lvalue

7 个答案:

答案 0 :(得分:11)

我能想到的唯一用途是减少函数声明的范围:

int main()
{
    void doSomething();
    doSomething();
    return 0;
}

void otherFunc()
{
    doSomething();  // ERROR, doSomething() not in scope
}

void doSomething()
{
    ...
}

当然,有更好的解决方案。如果需要隐藏一个函数,则应该通过将函数移动到单独的模块中来重构代码,以便需要调用要隐藏的函数的函数都在同一个模块中。然后,您可以通过将其声明为静态(C方式)或将其置于匿名命名空间(C ++方式)中来使该功能模块本地化。

答案 1 :(得分:2)

这是一个前向声明原型。可以想象,如果你有许多本地函数,或者本地函数彼此调用违反定义的顺序,你可能需要它。

答案 2 :(得分:2)

我能看到的唯一合理用途是只允许编译单元中的一个函数知道另一个编译单元中定义的函数。我认为这是一个有点合理的用途,但这是我能想到的唯一一个,我觉得这太过分了。

答案 3 :(得分:2)

当我想将它们作为参数传递给其他函数时,我希望在C中使用局部函数声明。我一直用其他语言做这件事。原因是封装了数据结构的实现。

E.g。我定义了一些数据结构,例如树或图,我不想公开其内部实现的细节,例如因为我可能想改变或改变它。所以我公开了其元素的访问器和mutator函数,以及遍历元素的遍历函数。遍历函数的参数是一个对元素进行操作的函数;遍历函数的任务是对每个元素执行参数函数,并可能以某种方式聚合结果。现在,当我调用遍历函数时,参数函数通常是一些依赖于本地状态的专用操作,因此应该定义为本地函数。必须推送函数,包含本地状态的变量,外部是全局的,或者是专门为保持它们而创建的内部类,这是非常难看的。但这是我用C和Java的问题,而不是C ++。

答案 4 :(得分:1)

就像在this answer的第3段中所说,它可以帮助范围阴影。

#include <stdio.h>

void c(); // Prototype of a function named ``c''

int main() {

    c(); // call the function

    { // additional scoppe needed for C, not for C++
        int c = 0; // shadow the c function with a c integer variable
        c++;
        {
            void c(); // hide the c integer variable back with the c function
            c();
        }
        ++c;
    } //!

    return 0;
}

void c() {
    printf("Called\n");
}

我不认为这种使用可能经常有用,并且很有可能在任何精心设计的程序中都不会出现这种情况。

我仍然认为这是该功能的最可能原因,最近定义功能,因为变量听起来不对。

答案 5 :(得分:0)

我有时这样做也是出于同样的原因我们被鼓励在第一次使用之前声明变量(而不是更早),即提高可读性。 (是的,我意识到对于变量来说它更重要,因为它让你无需在你认为第一次使用之前检查变量是否被使用)。将原型(特别是如果它比c()更多地涉及)接近函数调用提高了可读性。特殊情况C c()误导人类这一事实是不幸的,但在当地宣布职能的一般想法是有道理的。

当然,对于已经在范围内的函数名称也是如此。为什么不在每次使用之前重新声明每个功能?我对此的回答是:适度做所有事情。太多的杂乱会妨碍可读性(以及可维护性 - 如果函数的签名发生变化)。因此,虽然我不会从中做出规则,但在本地声明函数有时很有用。

答案 6 :(得分:-1)

如果要在声明不带参数的函数和使用默认析构函数实例化类之间有所不同,请跳过括号。

class C
{
  public:
    void foo() {}
};


int main()
{
    // declare function d, taking no arguments, returning fresh C
    C d();

    // instantiate class (leave parenthesis out)
    C c;
    c.foo();

    // call declared function
    C goo = d();

    return 0;
}

C d()
{
    C c;
    // ..
    return c;
}