2010-02-13 27 views
11

¿Podría alguien decirme si esto es posible en C o C++?¿es posible en C o C++ crear una función dentro de otra?

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

o algo similar, como p. una clase dentro de una función?

gracias por sus respuestas,

+1

Esto realmente no merece una 'respuesta'. "Sí." La advertencia es que la función tiene un alcance, por lo que solo puede referirse a ella por su nombre dentro de la función dada. Sin embargo, aún puede hacer un puntero a la función que lo apunte y arrojar eso a otro lado. –

+0

¡Sí! puede que tengas razón de que realmente no merece una 'respuesta', pero cuando tratamos de resolverla durante horas, buscamos cualquier solución ... Nunca lo he hecho pero estoy pidiendo ayuda para resolver mi problema. .. ¡Gracias! – make

+4

@Conspicuo compilador: puede o no merecer una respuesta, pero la respuesta ciertamente no es un simple "sí". –

Respuesta

29

Guau, ¡me sorprende que nadie haya dicho que sí! Las funciones gratuitas no pueden anidarse, pero los funtores y las clases en general pueden hacerlo.

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

    int q = fun_b(); 
    ... 
} 

Puede darle al operador un constructor y pasar referencias a variables locales para conectarlo al ámbito local. De lo contrario, puede acceder a otros tipos locales y variables estáticas. Sin embargo, las clases locales no pueden ser argumentos para las plantillas.

+6

Tenga en cuenta que C++ 0x (bah, poco a poco empiezo a odiar a todos los que "tenga en cuenta que en C++ 0x" -notas) los tipos locales derivarán su vinculación de la función adjunta , entonces podrás ponerlos en las listas de argumentos de la plantilla :) –

+0

@Potatoswatter: Buen punto. –

+0

¡Maldición! ¡Nunca supe que las definiciones de struct o clase fueran legales dentro de una función! ¡Potatoswatter! Usted gana el premio 'C++ gurú maestro'. –

1

No es posible declarar una función dentro de una función. Sin embargo, puede declarar una función dentro de un espacio de nombres o dentro de una clase en C++.

+0

gracias! el problema es que estoy usando MexFunction() como función principal y tengo un problema para incluir varios hilos en él. ¡gracias de nuevo! – make

+0

@mk: es posible que desee publicar otra pregunta específicamente sobre su problema de múltiples hilos (con más detalles). No estoy seguro de qué multi-threading tendría que ver con las funciones de anidación (más bien - No estoy seguro de por qué multi-threading necesitaría funciones anidadas). –

+0

gracias! mi problema está aquí: http://stackoverflow.com/questions/2256444/how-to-write-pthread-create-on-the-same-function, gracias de nuevo – make

7

C++ no admite funciones anidadas, sin embargo, puede usar algo como boost::lambda.

+0

gracias! Realmente quiero resolver mi problema sin utilizar las bibliotecas de impulso – make

5

No, pero en C++ 0x puede http://en.wikipedia.org/wiki/C%2B%2B0x#Lambda_functions_and_expressions, que puede tardar unos años más para ser totalmente compatible. El estándar no está completo en el momento de escribir esto.

operación -Editar-

Si puede utilizar MSVC 2010. Me corrió el código de abajo con éxito

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); 
} 

salida

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

(I escribió en >> c:\dev\loc\uniqueName.txt la sección de argumentos de trabajo del proyecto y la copia pegaron este resultado)

+1

Jaja ... Me acabo de dar cuenta de que no cumplieron su objetivo de completar el estándar en 2010. "C++ 0x" ya no es un término apropiado. Tendrán que redubularlo "C++ 1x" o "C++ xx" ... bastante triste que les haya tomado más de 10 años. – mpen

+0

@Mark: "Aunque el estándar no se entregará antes de 2010, hemos elegido mantener la designación informal C++ 0X, para no introducir ninguna confusión adicional". - http://groups.google.com/group/comp.std.c++/browse_thread/thread/5aa7115a76eaeb33 – kennytm

+2

@Mark: también tenga en cuenta que la x podría ser un número hexadecimal, lo que le permite saltar hasta F. –

6

C - Sí para gcc as an extension.

C++ - No.

+0

¡agradable! No sabía que esto existía. –

+1

+1 a malo esto no se lleva a C++! –

+0

gracias! El programa que estoy ejecutando contiene el código C y C++ – make

1

Aunque C y C++ ambos prohíben las funciones anidadas, algunos compiladores las admiten de todos modos (por ejemplo, si la memoria sirve, gcc puede, al menos con los indicadores de la derecha). Un functor anidado es mucho más portátil.

4

El término que está buscando es función anidada. Ni el estándar C ni el C++ permiten funciones anidadas, pero GNU C lo permite como una extensión. Aquí hay un buen wikipedia article sobre el tema.

3

Clang/Apple están trabajando en 'bloques', funciones anónimas en C! :-D

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

información here y spec here y Ars Technica tiene a bit en él

1

No hay funciones anidadas en C/C++, por desgracia.

3

No, y hay al menos una razón por la que complicar las cosas permitirlo. Generalmente, se espera que las funciones anidadas tengan acceso al alcance adjunto. Esto lo hace para que la "pila" ya no se pueda representar con una estructura de datos de pila. En cambio, se necesita un árbol completo.

Considere el siguiente código que realmente se compila en gcc como sugiere 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; 
} 

he puesto lo que la mayoría de la gente espera para ser impreso, pero en realidad, esto se imprime:

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

en cuenta que la última línea llama a la función "cuadrado", pero el " un "valor al que accede se modificó durante la llamada envoltura (4). Esto se debe a que no se crea un marco de "pila" separado para cada invocación de "envoltorio".

Tenga en cuenta que este tipo de funciones anidadas son bastante comunes en otros lenguajes que las admiten como lisp y python (e incluso versiones recientes de Matlab). Conducen a algunas capacidades de programación funcional muy poderosas, pero impiden el uso de una pila para contener marcos de ámbito local.

+0

Sé que no está claro, pero dudo que me haya preguntado si puedes crear una función en una función y llamarla fuera de la función (no tiene sentido por razones de alcance como en un {} bloque y también por las razones que ha mencionado) –

2

Puede anidar un local class dentro de una función, en cuyo caso la clase solo será accesible para esa función. A continuación, puede escribir su función anidada como un miembro de la clase local:

#include <iostream> 

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

    return g(); 
} 

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

tener en cuenta, sin embargo, que no se puede pasar una función definida en una clase local a un algoritmo STL, como 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 
} 

El error que se podrían obtener de GCC es "test.cpp: 18: Error: ninguna función coincidente para la llamada a` sort (__ __ gnu_cxx :: normal_iterator>>, __gnu_cxx :: __ normal_iterator>>, f () :: G &) ' "

+0

gracias!¿Puede por favor ayudarme con esto: http://stackoverflow.com/questions/2256444/how-to-write-pthread-create-on-the-same-function, gracias de nuevo – make

5

no se puede crear una función dentro de otra función en C++.

Sin embargo, puede crear un funtor clase local:

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

en C++ 0x puede crear una expresión lambda:

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

gracias! ¿Puede por favor ayudarme con esto: http://stackoverflow.com/questions/2256444/how-to-write-pthread-create-on-the-same-function, gracias de nuevo – make

1

Como han mencionado otras respuestas, estándar de C y C++ hacer no le permite definir funciones anidadas. (Algunos compiladores podrían permitirlo como una extensión, pero no puedo decir que lo haya visto usado).

Puede declarar otra función dentro de una función para que pueda ser llamado, pero la definición de esa función debe existir fuera de la función actual:

#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; 
} 

Una declaración de la función sin una explícita 'especificador de vinculación 'tiene un enlace extern.Entonces, mientras la declaración del nombre foo en la función main() tiene un alcance de main(), se vinculará a la función foo() que se define más adelante en el archivo (o en otro archivo si está definido foo()).

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

O lambda's en C++ 0x.

+0

gracias! ¿Puede por favor ayudarme con esto: http://stackoverflow.com/questions/2256444/how-to-write-pthread-create-on-the-same-function, gracias de nuevo – make

+0

Simplemente reemplace el cuerpo de local_foo con su hilo función. – MSN

Cuestiones relacionadas