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

Кто-то мог сказать мне, если это возможно в C или C++?

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

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

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

12
задан make 13 February 2010 в 17:11
поделиться

15 ответов

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

-121--2739853-

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

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

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

-121--2739862-

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

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

   int q = fun_b();
   ...
}

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

30
ответ дан 2 December 2019 в 02:53
поделиться

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

#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: error: нет соответствующей функции для вызова метода" sort (__ gnu _ cxx:: __ normal _ iterator > >, __ gnu _ cxx:: __ normal _ iterator > >, f ():: G &) " "

-121--2739847-

нельзя создать функцию внутри другой функции в 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();
}
-121--2739857-

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

Объявление функции без явного «спецификатора связи» имеет внешнюю связь . Таким образом, в то время как объявление имени foo в функции main () имеет область действия main () , оно будет связано с функцией foo () , которая определена позже в файле (или в другом файле, если определено foo () ).

1
ответ дан 2 December 2019 в 02:53
поделиться

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

1
ответ дан 2 December 2019 в 02:53
поделиться

Как отметил Брайан , динамические элементы управления следует загружать в Page_Init, а не в Page_Load.

Как поясняет это описание жизненного цикла страницы , к моменту возникновения события Page_Load состояние представления из обратной передачи уже обработано (в PreLoad). Если элементы управления еще не были перезагружены, состояние представления будет негде.

PreLoad:

Используйте это событие, если необходимо выполнить обработка на странице или элементе управления перед событием Load.

Прежде чем экземпляр Page поднимет это событие, оно загружает состояние просмотра для себя и все элементы управления , а затем процессы любые данные обратной передачи, включенные в Экземпляр запроса.

-121--4407369-

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

C++ - No.

-121--2739859-

Не в стандартном C, но gcc и clang поддерживают их в качестве расширения. См. интерактивное руководство по gcc .

1
ответ дан 2 December 2019 в 02:53
поделиться
void foo()
{
    class local_to_foo 
    { 
         public: static void another_foo() 
         { printf("whatevs"); } 
    };
    local_to_foo::another_foo();
}

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

3
ответ дан 2 December 2019 в 02:53
поделиться

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

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

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

3
ответ дан 2 December 2019 в 02:53
поделиться

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

1
ответ дан 2 December 2019 в 02:53
поделиться

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

7
ответ дан 2 December 2019 в 02:53
поделиться

Нет, но в 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);
}

output

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

(я написал >> c: \ dev \ loc \ uniqueName .txt в разделе рабочих аргументов проекта и скопируйте и вставьте этот результат)

5
ответ дан 2 December 2019 в 02:53
поделиться

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

Проблема с выводом связана с тем, что обработчик по умолчанию для модуля регистрации использует StreamHandler. Лучший способ справиться с этим - создать собственные обработчики. В случае, когда вы хотите использовать модуль регистрации по умолчанию, вы можете сделать что-то подобное:

# Get the default logger
default_logger = logging.getLogger('')

# Add the handler
default_logger.addHandler(myotherhandler)

# Remove the default stream handler
for handler in default_logger.handlers:
    if isinstance(handler, logging.StreamHandler):
        default_logger.removeHandler(handler)

Также на данный момент я перешел к использованию очень хорошего проекта Tornado для моих встроенных http-серверов.

-121--3147670-

Мои два цента. Вы/можете ли вы установить инструмент резервного копирования Joomla, такой как Joomlapack?

Я настроил его на запуск через сценарий CHRON, чтобы держать товары удобными в случае, если грабители дойдут до ограбления.

Какую версию Joomla вы используете?

1,0 .X версии больше не обновляются, и их возраст действительно начинает показывать. Вы обязаны сделать резервное копирование и планируете обновить до 1,5 и предвидеть чудеса 1,6

-121--740808-

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

C++ - No.

6
ответ дан 2 December 2019 в 02:53
поделиться

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

4
ответ дан 2 December 2019 в 02:53
поделиться

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

1
ответ дан 2 December 2019 в 02:53
поделиться

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

Рассмотрим следующий код, который действительно компилируется в 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

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

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

3
ответ дан 2 December 2019 в 02:53
поделиться

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

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

2
ответ дан 2 December 2019 в 02:53
поделиться

вы не можете создать функцию внутри другой функции в 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
ответ дан 2 December 2019 в 02:53
поделиться