2014-11-26 26 views
5

Supponiamo che una classe esiste come segue:Ritorno da funzione void

class Foo 
{ 
    void do_after_something() 
    { 
    //some code here 
    return; 
    } 

    void do_something() 
    { 
    //some code here 
    return do_after_something(); //returning another (void) function 
    } 
}; 

JAVA è nettamente contraria a qualcosa come quanto sopra, Borland C++ compilatore genera un avviso, MS VC++ non si lamenta.

La mia domanda è: il ritorno da una funzione di vuoto deve essere logicamente (teoricamente) corretto?

return do_after_something(); 

in contrapposizione a:

do_after_something(); 
return; 

o è tutto implementazione (compilatore/lingua) dipendente?

+0

Ha senso ma non in Java o C++ per cui restituire vuoto è denotato da un ritorno senza argomento. Ad ogni modo, spesso vedi una funzione di ritorno del vuoto come una procedura, cioè un pezzo di codice con un effetto collaterale, piuttosto che una funzione che calcola ... nessun valore. –

+5

Beh sì, dipende dalla lingua. Potresti facilmente immaginare un linguaggio chiamato Vava che è lo stesso di Java tranne per questa cosa. –

+0

Ricorda che entrambi questi linguaggi si sono evoluti da C che originariamente non aveva "void". Tutte le funzioni sono state definite per restituire qualcosa ('int' di default), e potresti assegnare una variabile al risultato di una funzione che non ha mai effettivamente restituito un valore, dandoti spazzatura. Dall'altra parte, in Algol/Pascal/Ada, scrivi una 'procedure' (che non restituisce un valore) o una' funzione' (che lo fa). Si potrebbe dire che una funzione 'void' è un tentativo di aggiungere una' procedure' a C per aiutare a prevenire l'uso di risultati garbage di funzioni che non restituiscono nulla. – ajb

risposta

8

Filosoficamente, si potrebbe sostenere che restituendo il risultato di una funzione -returning void dovrebbe essere consentito, ma, purtroppo, che non è il caso qui, almeno per Java.

E è valido per C++ tuttavia. Se si prova il seguente programma:

#include <iostream> 

void xyzzy(void) {} 
void plugh(void) { return xyzzy();} 

int main() { 
    std::cout << "Hello\n"; 
    plugh(); 
    return 0; 
} 

funzionerà correttamente.

Questo è dettagliata in ISO C++11 6.6.3 /3:

Un'istruzione ritorno con un'espressione di tipo void può essere utilizzato solo in funzione con un tipo di ritorno di cv void; l'espressione viene valutata appena prima che la funzione ritorni al suo chiamante.

quindi è davvero ugualmente valido sostenere che il modo in cui Java è corretta se si pensa di void come non un tipo effettivo, ma come un assenza di qualcosa. Ad esempio, quando si dispone di:

int xyzzy(void) { return 42; } 

in C, non sei obbligato a fornire un argomento del corretto (non) di tipo, come ad esempio con:

void plugh; 
int twisty = xyzzy(plugh); 

Idem, il C++ anche il modo è corretto, ma in un modo diverso: le lingue sono quello che sono.

+1

Quindi è la realtà che anche se entrambe le teorie sono verosimilmente corrette, rimani bloccato con la scelta dell'implementazione selezionata dalla lingua. Credo di poter vivere con quello. –

1

In C++ 11 è possibile e legale. È possibile restituire una funzione di vuoto da un'altra funzione di vuoto. Refrence Il linguaggio di programmazione C++ Capitolo 12, Bjarne Strousstrup

2

Penso che dovrebbe essere consentito e considerato valido in tutte le lingue. Se si dispone di una funzione il cui tipo restituito è void e si restituisce il risultato di un'espressione il cui tipo è void (ad esempio chiamando un'altra funzione void), è stato soddisfatto tale vincolo.

Non è considerato utile farlo in C (anche se penso che possa essere consentito) perché non c'è motivo di averne bisogno.Ogni volta che si fa:

return someVoidFn(); 

È sempre possibile tradurre la a:

someVoidFn(); 
return; 

E ottenere lo stesso effetto esattamente.

Tuttavia, in C++ e Java, la restituzione di una funzione void ha un uso reale, e questo perché tali lingue hanno modelli e generici. Considerate questo (non molto utile) classe Java:

class NestedIdentity<T> { 
    T run(int i, T value) { 
    if (i == 0) return value; 
    return run(i - 1); 
    } 
} 

Il suo metodo di run restituisce il valore che si passa ad esso, dopo aver chiamato in sé un certo numero di volte. Lo so, inutile, vero? Ma la parte importante è che Tpuò essere annullato. Si può fare questo:

NestedIdentity<Void> nest = new NestedIdentity<Void>(); 
nest(5, null); 

E questo funziona. In Java, Void (nota la maiuscola) crea un'istanza di un generico con un tipo-void -like il cui unico valore è null. Se Java non consente di restituire un'espressione void in un metodo void, dovrebbe essere un errore in fase di compilazione per creare un'istanza generica con vuoto.