2010-08-08 20 views
11

Si consideri il seguente frammento di codice:di ritorno da una funzione void in C++

void Foo() 
{ 
    // ... 
} 

void Bar() 
{ 
    return Foo(); 
} 

Che cosa è un motivo legittimo per utilizzare quanto sopra in C++ in contrasto con l'approccio più comune:

void Foo() 
{ 
    // ... 
} 

void Bar() 
{ 
    Foo(); 

    // no more expressions -- i.e., implicit return here 
} 

risposta

16

Probabilmente non utilizzare nel tuo esempio, ma ci sono alcune situazioni in cui è difficile gestire lo void nel codice del modello e, a volte, mi aspetto che questa regola sia d'aiuto. esempio molto artificiosa:

#include <iostream> 

template <typename T> 
T retval() { 
    return T(); 
} 

template <> 
void retval() { 
    return; 
} 

template <> 
int retval() { 
    return 23; 
} 

template <typename T> 
T do_something() { 
    std::cout << "doing something\n"; 
} 

template <typename T> 
T do_something_and_return() { 
    do_something<T>(); 
    return retval<T>(); 
} 

int main() { 
    std::cout << do_something_and_return<int>() << "\n"; 
    std::cout << do_something_and_return<void*>() << "\n"; 
    do_something_and_return<void>(); 
} 

Nota che solo main deve far fronte al fatto che nel caso void non c'è niente di ritorno da retval. La funzione intermedia do_something_and_return è generica.

Ovviamente questo ti porta solo lontano - se il do_something_and_return voleva, nel caso normale, memorizzare retval in una variabile e fare qualcosa con esso prima di tornare, allora saresti ancora nei guai - dovresti specializzare (o sovraccaricare) do_something_and_return per vuoto.

+0

Grazie. Tutte le risposte erano buone, ma questo ha ben illustrato il punto. – kirk0

0

L'unica La ragione per cui posso pensare è se avessi una lunga lista di istruzioni return Foo(); in un interruttore e volessi renderla più compatta.

9

Questa è una costruzione piuttosto inutile che non ha scopo, a meno che non venga utilizzata con i modelli. Cioè, se hai definito funzioni template che restituiscono un valore che può essere "void".

+4

quindi difficilmente "inutile", vero? ;) – jalf

+0

@jalf: Beh, nella forma mostrata nella domanda è piuttosto inutile, non è vero? ;-) –

+0

abbastanza vero. Ho interpretato il codice della domanda come un esempio della funzione della lingua e ho chiesto quando la funzione lingua * in generale * è utile. Ma giusto punto. ;) – jalf

7

Lo si utilizzerà in un codice generico, in cui il valore di ritorno di Foo() è sconosciuto o soggetto a modifiche. Prendere in considerazione:

template<typename Foo, typename T> T Bar(Foo f) { 
    return f(); 
} 

In questo caso, la barra è valida per void, ma è valida anche nel caso in cui il tipo di reso cambi. Tuttavia, se si limitasse a chiamare f, questo codice si interromperebbe se T fosse non vuoto. Utilizzando il ritorno f(); la sintassi garantisce la conservazione del valore di ritorno di Foo() se ne esiste uno, E consente di void().

Inoltre, il ritorno esplicito è una buona abitudine per entrare.

4

Modelli:

template <typename T, typename R> 
R some_kind_of_wrapper(R (*func)(T), T t) 
{ 
    /* Do something interesting to t */ 
    return func(t); 
} 

int func1(int i) { /* ... */ return i; } 

void func2(const std::string& str) { /* ... */ } 

int main() 
{ 
    int i = some_kind_of_wrapper(&func1, 42); 

    some_kind_of_wrapper(&func2, "Hello, World!"); 

    return 0; 
} 

senza essere in grado di restituire vuoto, il return func(t) nel modello non funzionava quando è stato chiesto per avvolgere func2.

0

Il motivo restituisce memoria come math.h restituisce sempre. math.h non ha nulla e nessun argomento vuoto. Ci sono molte situazioni pratiche in cui hai bisogno di memoria.

+0

Cosa?Le funzioni matematiche accettano argomenti e restituiscono valori perché è ciò che devono fare per essere funzioni matematiche ... – GManNickG

0

Potrebbe essere un caso in cui Foo() ha originariamente restituito un valore, ma in seguito è stato modificato in void e la persona che l'ha aggiornato non ha pensato molto chiaramente.

Problemi correlati