在C或C ++中是否可以在另一个内部创建一个函数?

时间:2010-02-13 06:00:32

标签: c++ c

有人可以告诉我这是否可以在C或C ++中使用?

void fun_a();
//int fun_b();
...
main(){
   ...
   fun_a();
   ...
   int fun_b(){
     ...
   }
   ...
} 

或类似的东西,例如函数内的一个类?

感谢您的回复,

15 个答案:

答案 0 :(得分:29)

哇,我很惊讶没有人说是的!自由函数不能嵌套,但函数和类通常可以。

void fun_a();
//int fun_b();
...
main(){
   ...
   fun_a();
   ...
   struct { int operator()() {
     ...
   } } fun_b;

   int q = fun_b();
   ...
}

您可以为仿函数提供构造函数并将对本地变量的引用传递给本地变量。否则,它可以访问其他本地类型和静态变量。但是,本地类不能是模板的参数。

答案 1 :(得分:7)

C ++不支持嵌套函数,但您可以使用类似boost::lambda的内容。

答案 2 :(得分:6)

C - 适用于gcc as an extension

C ++ - 不。

答案 3 :(得分:5)

否,但在C ++ 0x中你可以http://en.wikipedia.org/wiki/C%2B%2B0x#Lambda_functions_and_expressions可能需要几年才能完全支持。在撰写本文时,该标准尚未完成。

-edit-

如果您可以使用MSVC 2010.我成功运行了以下代码

void test()
{
 []() { cout << "Hello function\n"; }();
 auto fn = [](int x) -> int { cout << "Hello function (" << x << " :))\n"; return x+1; };
 auto v = fn(2);
 fn(v);
}

输出

Hello function
Hello function (2 :))
Hello function (3 :))

(我在项目工作参数部分写了>> c:\dev\loc\uniqueName.txt并复制粘贴了这个结果)

答案 4 :(得分:5)

你不能在C ++中的另一个函数内创建一个函数。

但是,您可以创建一个本地类函数:

int foo()
{
   class bar
   {
   public:
      int operator()()
      {
         return 42;
      }
   };
   bar b;
   return b();
}

在C ++ 0x中,您可以创建一个lambda表达式:

int foo()
{
   auto bar = []()->int{return 42;};
   return bar();
}

答案 5 :(得分:4)

您正在寻找的术语是嵌套函数。标准C和C ++都不允许嵌套函数,但GNU C允许它作为扩展。关于这个问题,这是一个很好的wikipedia article

答案 6 :(得分:3)

Clang / Apple正在研究C中的'块',匿名函数! :-D

  

^(void){printf(“hello world \ n”); }

info herespec here,ars technica上有a bit

答案 7 :(得分:3)

不,并且至少有一个原因会导致事情变得复杂化。嵌套函数通常需要访问封闭范围。这使得“堆栈”不再能够用堆栈数据结构表示。相反,需要一个完整的树。

考虑以下代码,它实际上是在KennyTM建议的gcc中编译的。

#include <stdio.h>

typedef double (*retdouble)();

retdouble wrapper(double a) {
  double square() { return a * a; }

  return square;
}

int use_stack_frame(double b) {
  return (int)b;
}

int main(int argc, char** argv) {
  retdouble square = wrapper(3);
  printf("expect  9 actual %f\n", square());
  printf("expect  3 actual %d\n", use_stack_frame(3));
  printf("expect 16 actual %f\n", wrapper(4)());
  printf("expect  9 actual %f\n", square());
  return 0;
}

我已经放置了大多数人希望打印的内容,但事实上,这会被打印出来:

expect  9 actual 9.000000
expect  3 actual 3
expect 16 actual 16.000000
expect  9 actual 16.000000

请注意,最后一行调用“square”函数,但在wrapper(4)调用期间修改了它访问的“a”值。这是因为没有为“wrapper”的每次调用创建单独的“堆栈”框架。

请注意,这些嵌套函数实际上在支持它们的其他语言中非常常见,如lisp和python(甚至是最新版本的Matlab)。它们带来了一些非常强大的函数编程功能,但它们排除了使用堆栈来保存局部范围框架。

答案 8 :(得分:3)

void foo()
{
    class local_to_foo 
    { 
         public: static void another_foo() 
         { printf("whatevs"); } 
    };
    local_to_foo::another_foo();
}

或者是C ++ 0x中的lambda。

答案 9 :(得分:2)

您可以在函数中嵌套local class,在这种情况下,该类只能被该函数访问。然后,您可以将嵌套函数编写为本地类的成员:

#include <iostream>

int f()
{
    class G
    {
    public:
        int operator()()
        {
            return 1;
        }
    } g;

    return g();
}

int main()
{
    std::cout << f() << std::endl;
}

但请记住,您无法将本地类中定义的函数传递给STL算法,例如sort()

int f()
{
    class G
    {
    public:
        bool operator()(int i, int j)
        {
            return false;
        }
    } g;

    std::vector<int> v;

    std::sort(v.begin(), v.end(), g);  //  Fails to compile
}

你从gcc得到的错误是“test.cpp:18:错误:没有匹配函数来调用`sort(__ gnu_cxx :: __ normal_iterator&gt;&gt;,__ gn_cxx :: __ normal_iterator&gt;&gt;,f( ):: G&安培)” “

答案 10 :(得分:1)

无法在函数中声明函数。但是,您可以在命名空间内或C ++中的类中声明一个函数。

答案 11 :(得分:1)

不在标准C中,但gccclang支持它们作为扩展名。请参阅the gcc online manual

答案 12 :(得分:1)

虽然C和C ++都禁止嵌套函数,但是一些编译器仍然支持它们(例如,如果内存服务,gcc可以,至少使用正确的标志)。嵌套仿函数虽然便携得多。

答案 13 :(得分:1)

不幸的是,C / C ++中没有嵌套函数。

答案 14 :(得分:1)

正如其他答案所提到的,标准C和C ++不允许您定义嵌套函数。 (有些编译器可能允许它作为扩展,但我不能说我已经看过它了。)

你可以声明函数内的另一个函数,以便可以调用它,但该函数的定义必须存在于当前函数之外:

#include <stdlib.h>
#include <stdio.h>

int main( int argc, char* argv[])
{
    int foo(int x);

    /*     
    int bar(int x) {  // this can't be done
        return x;
    }
    */

    int a = 3;

    printf( "%d\n", foo(a));

    return 0;
}


int foo( int x) 
{
    return x+1;
}

没有明确的“链接说明符”的函数声明具有extern链接。因此,虽然函数foo中名称main()的声明范围限定为main(),但它将链接到稍后在文件中定义的foo()函数(或另一个文件,如果那是foo()定义的地方。