Можно ли в C или C ++ создать функцию внутри другой? - PullRequest
11 голосов
/ 13 февраля 2010

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

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

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

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

Ответы [ 15 ]

29 голосов
/ 13 февраля 2010

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

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

   int q = fun_b();
   ...
}

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

7 голосов
/ 13 февраля 2010

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

6 голосов
/ 13 февраля 2010

C - Да для gcc в качестве расширения .

C ++ - Нет.

5 голосов
/ 13 февраля 2010

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

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

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

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

int foo()
{
   auto bar = []()->int{return 42;};
   return bar();
}
5 голосов
/ 13 февраля 2010

Нет, но в 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 голосов
/ 13 февраля 2010

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

3 голосов
/ 13 февраля 2010
void foo()
{
    class local_to_foo 
    { 
         public: static void another_foo() 
         { printf("whatevs"); } 
    };
    local_to_foo::another_foo();
}

Или лямбда в C ++ 0x.

3 голосов
/ 13 февраля 2010

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

Рассмотрим следующий код, который на самом деле компилируется в 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). Они приводят к некоторым очень мощным функциональным возможностям программирования, но они исключают использование стека для хранения локальных фреймов области видимости.

3 голосов
/ 13 февраля 2010

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

^ (void) {printf ("Привет, мир \ n"); }

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

2 голосов
/ 13 февраля 2010

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

#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>>, __gnu_cxx :: __ normal_iterator>>, f () :: G & )» «

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...