tipos - todas las funciones de c++
¿Hay algún uso para las declaraciones de funciones locales? (7)
A veces lo hago por el mismo motivo por el que se nos anima a declarar las variables justo antes de su primer uso (y no antes), es decir, para mejorar la legibilidad. (Sí, me doy cuenta de que para las variables es más importante porque le libera de la necesidad de verificar si la variable se usa antes de lo que cree que es su primer uso). Tener el prototipo (especialmente si es más complicado que solo c()
) cerca de la invocación de la función mejora la legibilidad. El hecho de que el caso especial C c()
sea engañoso para los humanos es desafortunado, pero la idea general de declarar funciones localmente tiene mérito.
Por supuesto, esto es cierto también para los nombres de funciones que ya están dentro del alcance. ¿Por qué no volver a declarar cada función antes de cada uso? Mi respuesta a eso: hacer todas las cosas con moderación. Demasiado desorden impide la legibilidad (así como la capacidad de mantenimiento, en caso de que la firma de la función cambie alguna vez). Entonces, aunque no haría una regla, a veces es útil declarar las funciones localmente.
La mayoría de los programadores de C ++ como yo han cometido el siguiente error en algún momento:
class C { /*...*/ };
int main() {
C c(); // declares a function c taking no arguments returning a C,
// not, as intended by most, an object c of type C initialized
// using the default constructor.
c.foo(); // compiler complains here.
//...
}
Ahora, mientras el error es bastante obvio, una vez que lo sepa, me preguntaba si existe algún uso razonable para este tipo de declaración de función local, excepto que puede hacerlo, especialmente porque no hay manera de definir una función local de este tipo en la misma. bloquear; Tienes que definirlo en otra parte.
Creo que las clases locales al estilo de Java son una característica bastante buena que tiendo a usar con frecuencia, especialmente la clasificación anónima. Incluso las clases locales de C ++ (que pueden tener funciones de miembro definidas en línea) tienen algún uso. Pero esta declaración de función local sin definición me parece muy incómoda. ¿Es solo un legado C o hay algún caso de uso más profundo del que no tengo conocimiento?
Edite para los no creyentes: C c()
no es una declaración de puntero de función.
Este programa
int main()
{
void g();
cout << "Hello ";
g();
return 0;
}
void g()
{
cout << "world." << endl;
}
Salidas Hello world.
Este programa
void fun()
{
cout << "world." << endl;
}
int main()
{
void g();
g = fun;
cout << "Hello ";
g();
return 0;
}
no compila gcc se queja:
error: cannot convert ''void ()()'' to ''void ()()'' in assignment
comeau
error: expression must be a modifiable lvalue
Como se dijo en el tercer fragmento de esta respuesta , puede ayudar con el sombreado del alcance.
#include <stdio.h>
void c(); // Prototype of a function named ``c''''
int main() {
c(); // call the function
{ // additional scoppe needed for C, not for C++
int c = 0; // shadow the c function with a c integer variable
c++;
{
void c(); // hide the c integer variable back with the c function
c();
}
++c;
} //!
return 0;
}
void c() {
printf("Called/n");
}
No creo que este uso pueda ser útil a menudo y hay posibilidades de que no surja en ningún programa bien diseñado.
Sigo pensando que esta es la razón más probable para esa característica, la definición de funciones últimamente ya que para las variables simplemente no suena bien.
El único uso que se me ocurre es reducir el alcance de las declaraciones de funciones:
int main()
{
void doSomething();
doSomething();
return 0;
}
void otherFunc()
{
doSomething(); // ERROR, doSomething() not in scope
}
void doSomething()
{
...
}
Por supuesto, hay soluciones mucho mejores para esto. Si necesita ocultar una función, realmente debería reestructurar su código moviendo las funciones a módulos separados para que las funciones que necesitan llamar a la función que desea ocultar estén todas en el mismo módulo. Luego, puede hacer que la función sea local al módulo declarándola estática (la forma C) o colocándola dentro de un espacio de nombres anónimo (la forma C ++).
El único uso sensato que puedo ver es permitir que solo una función en una unidad de compilación conozca una función definida en otra unidad de compilación. Creo que sería un uso razonable, pero ese es el único en el que puedo pensar, y creo que eso es una exageración.
Es un prototipo de declaración hacia adelante. Posiblemente, si tiene muchas funciones locales, o funciones locales que se llaman entre sí en contra del orden de definición, es posible que lo necesite.
He querido declaraciones de funciones locales en C cuando quería pasarlas como argumentos a alguna otra función. Hago esto todo el tiempo en otros idiomas. El motivo es encapsular la implementación de estructuras de datos.
Por ejemplo, defino una estructura de datos, por ejemplo, un árbol o una gráfica, y no quiero exponer los detalles de su implementación interna, por ejemplo, porque es posible que desee cambiarla o modificarla. Así que expongo funciones de acceso y mutador para sus elementos, y una función transversal para iterar sobre los elementos. La función de recorrido tiene como argumento una función que opera en un elemento; La tarea de la función transversal es ejecutar la función de argumento en cada elemento y posiblemente agregar los resultados de alguna manera. Ahora, cuando llamo a la función transversal, la función de argumento suele ser una operación especializada que depende del estado local y, por lo tanto, debe definirse como una función local. Tener que empujar la función, con las variables que contienen el estado local, fuera de ser global, o en una clase interna creada específicamente para mantenerlas, es feo. Pero este es un problema que tengo con C y Java, no con C ++.
Si desea diferenciar entre declarar una función sin parámetros y crear una instancia de una clase con el destructor predeterminado, omita el paréntesis.
class C
{
public:
void foo() {}
};
int main()
{
// declare function d, taking no arguments, returning fresh C
C d();
// instantiate class (leave parenthesis out)
C c;
c.foo();
// call declared function
C goo = d();
return 0;
}
C d()
{
C c;
// ..
return c;
}