2010-02-13 7 views
11

Qualcuno potrebbe dirmi se questo è possibile in C o C++?è possibile in C o C++ creare una funzione all'interno di un'altra?

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

o qualcosa di simile, come ad es. una classe in una funzione?

grazie per le vostre risposte,

+1

Questo in realtà non merita una "risposta". "Sì." L'avvertenza è la funzione è scopata, quindi è possibile fare riferimento ad esso solo per nome all'interno della funzione data. Puoi comunque creare un puntatore a funzione che punta ad esso e lanciarlo altrove, comunque. –

+0

Sì! potresti avere ragione che in realtà non merita una "risposta", ma quando cerchiamo di risolvere per ore, cerchiamo qualsiasi soluzione ... Non l'ho mai fatto, ma sto cercando un aiuto per risolvere il mio problema. .. Grazie! – make

+4

Compilatore @Conspicuous: può o non può meritare una risposta, ma la risposta certamente non è un semplice "sì". –

risposta

29

Wow, sono sorpreso che nessuno abbia detto di si! Le funzioni libere non possono essere annidate, ma i funtori e le classi in generale possono.

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

    int q = fun_b(); 
    ... 
} 

Si può dare il funtore un costruttore e trasmettere i riferimenti alle variabili locali per collegarlo al campo di applicazione locale. Altrimenti, può accedere ad altri tipi locali e variabili statiche. Le classi locali non possono essere argomenti ai template, però.

+6

Nota che C++ 0x (bah, lentamente comincio a odiare tutti quei "noti in C++ 0x" -notes) i tipi locali deriveranno il loro collegamento dalla funzione di chiusura , quindi sarai in grado di metterli in elenchi di argomenti template :) –

+0

@Potatoswatter: buon punto. –

+0

Dann! Non ho mai saputo che le struct o le definizioni di classe fossero legali all'interno di una funzione! Potatoswatter! Vinci il premio "C++ guru master". –

1

Non è possibile dichiarare una funzione all'interno di una funzione. È possibile, tuttavia, dichiarare una funzione all'interno di uno spazio dei nomi o all'interno di una classe in C++.

+0

grazie! il problema è che sto usando MexFunction() come funzione principale e ho un problema a includere multi-thread su di esso. grazie ancora! – make

+0

@mk: potresti voler postare un'altra domanda specifica sul tuo problema multi-thread (con maggiori dettagli). Non sono sicuro di quale multi-threading dovrebbe fare con le funzioni di nidificazione (piuttosto - non sono sicuro del motivo per cui il multi-threading necessiterebbe di funzioni annidate). –

+0

grazie! il mio problema è qui: http://stackoverflow.com/questions/2256444/how-to-write-pthread-create-on-the-same-function, grazie ancora – make

7

C++ non supporta le funzioni annidate, tuttavia è possibile utilizzare qualcosa come boost::lambda.

+0

grazie! Voglio davvero risolvere il mio problema senza usare le librerie di boost – make

5

No, ma in C++ 0x è possibile http://en.wikipedia.org/wiki/C%2B%2B0x#Lambda_functions_and_expressions che potrebbe richiedere alcuni anni per supportare completamente. Lo standard non è completo al momento della stesura di questo documento.

operativa -Editazione-

Se è possibile utilizzare MSVC 2010. Ho eseguito il codice qui sotto con successo

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

uscita

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

(ho scritto in >> c:\dev\loc\uniqueName.txt la sezione degli argomenti di lavoro del progetto e copia incollata questo risultato)

+1

Haha .. Ho appena realizzato che mancavano il loro obiettivo di completare lo standard entro il 2010. "C++ 0x" non è più un termine appropriato. Dovranno ridurlo "C++ 1x" o "C++ xx" ... piuttosto triste che li abbia portati più di 10 anni. – mpen

+0

@Mark: "Anche se lo standard non verrà consegnato prima del 2010, abbiamo scelto di mantenere la designazione informale C++ 0X, in modo da non introdurre alcuna ulteriore confusione." - http://groups.google.com/group/comp.std.c++/browse_thread/thread/5aa7115a76eaeb33 – kennytm

+2

@Mark: nota anche che x potrebbe essere un numero esadecimale, permettendogli di saltare a F. –

6

C - Sì per gcc as an extension.

C++ - No.

+0

bello! non sapevo che esistesse. –

+1

+1 a male questo non è portato in C++! –

+0

grazie! Il programma che sto utilizzando contiene codice C e C++ – make

1

Sebbene C e C++ proibiscano entrambe le funzioni annidate, alcuni compilatori supportano comunque (ad es., Se la memoria serve, gcc può, almeno con i flag corretti). Tuttavia, un functor annidato è molto più portatile.

4

Il termine che stai cercando è funzione nidificata. Né C standard né C++ standard consentono funzioni nidificate, ma GNU C lo consente come un'estensione. Ecco un buon wikipedia article sull'argomento.

3

Clang/Apple stanno lavorando su "blocchi", funzioni anonime in C! :-D

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

informazioni here e spec here, e ars technica ha a bit su di esso

1

Nessun funzioni annidate in C/C++, purtroppo.

3

No, e c'è almeno una ragione per cui complicherebbe le cose per consentirlo. In genere, è previsto che le funzioni annidate abbiano accesso all'ambito che racchiude. Ciò lo rende così che lo "stack" non può più essere rappresentato con una struttura di dati dello stack. Invece è necessario un albero completo.

Si consideri il seguente codice che in realtà compila in gcc come suggerisce 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; 
} 

ho messo quello che la maggior parte delle persone si aspettano di essere stampato, ma in realtà, questo viene stampato:

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

Si noti che l'ultima riga chiama la funzione "piazza", ma il " un "valore a cui accede è stato modificato durante la chiamata wrapper (4). Questo perché un frame "stack" separato non viene creato per ogni invocazione di "wrapper".

Si noti che questi tipi di funzioni annidate sono in realtà abbastanza comuni in altri linguaggi che li supportano come lisp e python (e anche versioni recenti di Matlab). Portano a funzionalità di programmazione funzionale molto potenti, ma precludono l'uso di uno stack per contenere frame di ambito locali.

+0

So che non è chiaro ma dubito che op stava chiedendo se è possibile creare una funzione in una funzione e chiamarla al di fuori della funzione (non ha senso per ragioni di ambito come lo è in un blocco {} e anche per i motivi che hai menzionato) –

2

È possibile nidificare un local class all'interno di una funzione, nel qual caso la classe sarà accessibile solo a tale funzione. Si potrebbe quindi scrivere la funzione nidificata come membro della classe locale:

#include <iostream> 

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

    return g(); 
} 

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

tenere a mente, però, che non è possibile passare una funzione definita in una classe locale per un algoritmo STL, come ad esempio 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 
} 

L'errore che si otterrebbe da gcc è "test.cpp: 18: Errore: nessuna funzione di corrispondenza per la chiamata a` sort (__ gnu_cxx :: __ normal_iterator>>, __gnu_cxx :: __ normal_iterator>>, f () :: G &) ' "

+0

grazie!puoi aiutarmi per favore con questo: http://stackoverflow.com/questions/2256444/how-to-write-pthread-create-on-the-same-function, grazie ancora – make

5

non è possibile creare una funzione all'interno di un'altra funzione in C++.

È possibile comunque creare un funtore classe locale:

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

in C++ 0x è possibile creare un'espressione lambda:

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

grazie! puoi aiutarmi per favore con questo: http://stackoverflow.com/questions/2256444/how-to-write-pthread-create-on-the-same-function, grazie ancora – make

1

Come altre risposte hanno detto, di serie C e C++ fare non consente di definire le funzioni nidificate. (Alcuni compilatori potrebbero consentirlo come estensione, ma non posso dire di averlo visto usato).

È possibile dichiarare un'altra funzione all'interno di una funzione in modo che si può chiamare, ma la definizione di tale funzione deve esistere al di fuori della funzione corrente:

#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 dichiarazione funzione senza un esplicito 'linkage specificatore 'ha un collegamento extern.Pertanto, mentre la dichiarazione del nome foo nella funzione main() è impostata su main(), verrà collegata alla funzione foo() definita in un secondo momento nel file (o in un altro file, se è stato definito foo()).

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

Oppure lambda in C++ 0x.

+0

grazie! puoi aiutarmi per favore con questo: http://stackoverflow.com/questions/2256444/how-to-write-pthread-create-on-the-same-function, grazie ancora – make

+0

Basta sostituire il corpo di local_foo con il thread funzione. – MSN

Problemi correlati