2010-08-08 11 views
11

Considere el siguiente fragmento:regreso de una función de cancelación en C++

void Foo() 
{ 
    // ... 
} 

void Bar() 
{ 
    return Foo(); 
} 

¿Qué es una razón legítima para usar lo anterior en C++ en comparación con el enfoque más común:

void Foo() 
{ 
    // ... 
} 

void Bar() 
{ 
    Foo(); 

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

Respuesta

16

Probablemente no use en su ejemplo, pero hay algunas situaciones en las que es difícil tratar con void en el código de la plantilla, y espero que esta regla ayude con eso a veces. ejemplo muy artificial:

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

en cuenta que sólo main tiene que hacer frente al hecho de que en el caso void no hay nada para volver de retval. La función intermedia do_something_and_return es genérica.

Por supuesto, esto solo lo lleva tan lejos - si do_something_and_return quería, en el caso normal, almacenar retval en una variable y hacer algo con eso antes de regresar, entonces aún estaría en problemas. Tendría que especializar (o sobrecargar) do_something_and_return para el vacío.

+0

Gracias. Todas las respuestas fueron buenas, pero esta ilustra el punto muy bien. – kirk0

0

El único La razón por la que puedo pensar es si tenía una larga lista de declaraciones return Foo(); en un interruptor y quería hacerlo más compacto.

9

Esta es una construcción bastante inútil que no sirve para nada, a menos que se use con plantillas. Es decir, si ha definido funciones de plantilla que devuelve un valor que puede ser 'vacío'.

+4

entonces no es "inútil", ¿verdad? ;) – jalf

+0

@jalf: Bueno, en la forma en que se muestra en la pregunta es bastante inútil, ¿no? ;-) –

+0

es suficiente. Interpreté el código en la pregunta como un ejemplo de la característica de idioma y pregunté cuándo la característica de idioma * en general * es útil. Pero punto justo. ;) – jalf

7

Lo usaría en código genérico, donde el valor de retorno de Foo() es desconocido o está sujeto a cambios. Considere lo siguiente:

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

En este caso, Bar tiene una validez de vacío, sino que también es válido si el cambio de tipo de cambio. Sin embargo, si simplemente llamara a f, este código se rompería si T no fuera nulo. Usando el retorno f(); la sintaxis garantiza la preservación del valor de retorno de Foo() si existe, Y permite el vacío().

Además, regresar explícitamente es un buen hábito para entrar.

4

Plantillas:

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

sin ser capaz de volver vacío, el return func(t) en la plantilla no funcionarían cuando se le pidió que envuelva func2.

0

El motivo es devolver la memoria como las matemáticas.h siempre regresa. math.h no tiene ningún vacío ni argumentos vacíos. Hay muchas situaciones prácticas en las que necesitas memoria.

+0

¿Qué?Las funciones matemáticas toman argumentos y devuelven valores porque eso es lo que tienen que hacer para ser funciones matemáticas ... – GManNickG

0

Podría ser un caso en el que Foo() originalmente devolvió un valor, pero más tarde se cambió a void, y la persona que lo actualizó simplemente no pensó muy claramente.

Cuestiones relacionadas