Может кто-нибудь скажет мне, возможно ли это на C или С++?
void fun_a();
//int fun_b();
...
main(){
...
fun_a();
...
int fun_b(){
...
}
...
}
или что-то подобное, например. класс внутри функции?
спасибо за ваши ответы,
Может кто-нибудь скажет мне, возможно ли это на C или С++?
void fun_a();
//int fun_b();
...
main(){
...
fun_a();
...
int fun_b(){
...
}
...
}
или что-то подобное, например. класс внутри функции?
спасибо за ваши ответы,
Ничего себе, я удивлен, что никто не сказал да! Свободные функции не могут быть вложенными, но функторы и классы вообще могут.
void fun_a();
//int fun_b();
...
main(){
...
fun_a();
...
struct { int operator()() {
...
} } fun_b;
int q = fun_b();
...
}
Вы можете дать функтору конструктор и передать ссылки на локальные переменные, чтобы подключить его к локальной области. В противном случае он может обращаться к другим локальным типам и статическим переменным. Однако локальные классы не могут быть аргументами для шаблонов.
С++ не поддерживает вложенные функции, однако вы можете использовать что-то вроде boost:: lambda.
C - Да для gcc как расширение.
С++ - Нет.
Нет, но в С++ 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
в разделе рабочих аргументов проекта и скопировал этот результат)
вы не можете создать функцию внутри другой функции в С++.
Однако вы можете создать локальный класс-функтор:
int foo()
{
class bar
{
public:
int operator()()
{
return 42;
}
};
bar b;
return b();
}
в С++ 0x вы можете создать выражение лямбда:
int foo()
{
auto bar = []()->int{return 42;};
return bar();
}
Термин, который вы ищете, - это вложенная функция. Ни стандартные C, ни С++ не допускают вложенных функций, но GNU C позволяет использовать его как расширение. Вот хорошая статья статьи в википедии по этому вопросу.
Clang/Apple работают над "блоками", анонимными функциями в C!:-D
^ (void) {printf ( "hello world\n" ); }
Нет, и есть по крайней мере одна причина, по которой это осложнит ситуацию. Предполагается, что вложенные функции имеют доступ к охватывающей области. Это делает так, что "стек" больше не может быть представлен структурой данных стека. Вместо этого требуется полное дерево.
Рассмотрим следующий код, который действительно компилируется в 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). Они приводят к некоторым очень мощным функциям функционального программирования, но они исключают использование стека для хранения локальных фреймов области.
void foo()
{
class local_to_foo
{
public: static void another_foo()
{ printf("whatevs"); }
};
local_to_foo::another_foo();
}
Или lambda в С++ 0x.
Вы можете вложить в функцию локальный класс внутри функции, и в этом случае класс будет доступен только этой функции. Затем вы можете записать свою вложенную функцию как член локального класса:
#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 &)" "
Невозможно объявить функцию внутри функции. Однако вы можете объявить функцию внутри пространства имен или внутри класса на С++.
Не в стандарте C, а gcc
и clang
поддерживают их как расширение. См. руководство пользователя gcc.
Хотя C и С++ запрещают вложенные функции, несколько компиляторов поддерживают их в любом случае (например, если память служит, gcc может, по крайней мере, с правильными флагами). Однако вложенный функтор гораздо более портативен.
К сожалению, нет вложенных функций в 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()
определяется).