Возможно ли в C или С++ создать функцию внутри другого?

Может кто-нибудь скажет мне, возможно ли это на C или С++?

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

или что-то подобное, например. класс внутри функции?

спасибо за ваши ответы,

Ответ 1

Ничего себе, я удивлен, что никто не сказал да! Свободные функции не могут быть вложенными, но функторы и классы вообще могут.

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

   int q = fun_b();
   ...
}

Вы можете дать функтору конструктор и передать ссылки на локальные переменные, чтобы подключить его к локальной области. В противном случае он может обращаться к другим локальным типам и статическим переменным. Однако локальные классы не могут быть аргументами для шаблонов.

Ответ 2

С++ не поддерживает вложенные функции, однако вы можете использовать что-то вроде boost:: lambda.

Ответ 4

Нет, но в С++ 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 в разделе рабочих аргументов проекта и скопировал этот результат)

Ответ 5

вы не можете создать функцию внутри другой функции в С++.

Однако вы можете создать локальный класс-функтор:

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

в С++ 0x вы можете создать выражение лямбда:

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

Ответ 6

Термин, который вы ищете, - это вложенная функция. Ни стандартные C, ни С++ не допускают вложенных функций, но GNU C позволяет использовать его как расширение. Вот хорошая статья статьи в википедии по этому вопросу.

Ответ 7

Clang/Apple работают над "блоками", анонимными функциями в C!:-D

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

info здесь и spec here, и ars technica имеет немного на нем

Ответ 8

Нет, и есть по крайней мере одна причина, по которой это осложнит ситуацию. Предполагается, что вложенные функции имеют доступ к охватывающей области. Это делает так, что "стек" больше не может быть представлен структурой данных стека. Вместо этого требуется полное дерево.

Рассмотрим следующий код, который действительно компилируется в gcc, как предлагает KennyTM.

#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

Обратите внимание, что последняя строка вызывает функцию "квадрат", но значение "a", которое она обращается, было изменено во время вызова оболочки (4). Это связано с тем, что отдельный кадр стека не создается для каждого вызова "обертки".

Обратите внимание: эти типы вложенных функций на самом деле довольно распространены в других языках, которые поддерживают их как lisp и python (и даже последние версии Matlab). Они приводят к некоторым очень мощным функциям функционального программирования, но они исключают использование стека для хранения локальных фреймов области.

Ответ 9

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

Или lambda в С++ 0x.

Ответ 10

Вы можете вложить в функцию локальный класс внутри функции, и в этом случае класс будет доступен только этой функции. Затем вы можете записать свою вложенную функцию как член локального класса:

#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: ошибка: нет соответствующей функции для вызова сортировки (__ gnu_cxx:: __ normal_iterator → , __gnu_cxx:: __ normal_iterator → , f():: G &)" "

Ответ 11

Невозможно объявить функцию внутри функции. Однако вы можете объявить функцию внутри пространства имен или внутри класса на С++.

Ответ 13

Хотя C и С++ запрещают вложенные функции, несколько компиляторов поддерживают их в любом случае (например, если память служит, gcc может, по крайней мере, с правильными флагами). Однако вложенный функтор гораздо более портативен.

Ответ 14

К сожалению, нет вложенных функций в C/С++.

Ответ 15

Как упоминалось в других ответах, стандартные 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() определяется).