2010-12-22 16 views
16

He estado usando la palabra clave static durante mucho tiempo para definir el enlace interno. Más tarde, cambié al estilo C++ de envolver cosas locales en espacios de nombres anónimos.Espacios de nombres anónimos: ¿Son realmente tan buenos?

Sin embargo, ahora que he trabajado con espacios de nombres anónimos durante algunos años, ¡empiezo a pensar que la palabra clave static es mucho más fácil de trabajar!

Un problema común es que tengo este patrón:

namespace { 
    // ...five pages of code... 
} // namespace 

Para ver si una determinada función tiene enlace interno o externo, ahora tengo que desplazarse mucho, en comparación con el estilo C de edad donde podría simplemente verificar si la función/objeto tenía static delante de él.

Sé que hay espacios de nombres anónimos que static no pueden - ocultar typedefs - pero personalmente no estoy muy interesado en eso, de todos modos.

¿Cuál es su opinión sobre esto? ¿Es la ganancia de espacios de nombres anónimos tan grande que garantiza la disminución de la legibilidad? ¿O estoy completamente equivocado?

+3

funciones 'estáticas' en el ámbito del espacio de nombres han quedado en desuso, eso es motivo suficiente para no usarlas. Las funciones en el espacio de nombres anónimo tienen todas las ventajas de 'static', excepto que tienen un enlace externo. El último, creo que ya está siendo atendido por los compiladores, eliminando nombres definidos en espacios de nombres anónimos de la sección exportada. –

+11

@Gene en realidad, las funciones estáticas nunca se desaprobaron. La depreciación fue solo contra * objetos *. Sin embargo, la obsolescencia se eliminó en n3225: en C++ 0x ya no está en desuso para usarlo para proporcionar enlaces internos a objetos o funciones. Otra diferencia es que los espacios de nombre sin nombre retendrían el enlace externo: los espacios de nombre sin nombre y su contenido obtendrán un enlace interno en C++ 0x. De modo que ya no parece haber ninguna diferencia entre el modo estático y el espacio de espacio de nombres, excepto que el espacio de nombre de nombres permitirá cosas como 'namespace {int a; } int a; '. –

+0

@Johannes: ¿C++ 0x permite parámetros de plantilla con enlace interno, o es un gran cambio de último momento? –

Respuesta

20

Si el código en el espacio de nombres es demasiado largo, no hay nada que le impida hacer esto:

namespace { 
    int foo(char* x) { 
     return x[0] + x[1]; 
    } 
} 

namespace { 
    int bar(char *x, char *y) { 
     return foo(x) + foo(y); 
    } 
} 

En C++ 03 la ventaja práctica de utilizar un espacio de nombres sin nombre es precisamente que los contenidos tienen externa vinculación, (pero aún son invisibles fuera de la TU porque no hay forma de referirse a ellos). los parámetros de plantilla no pueden tener vinculación interna:

namespace { 
    int foo(const char* x) { 
     return x[0] + x[1]; 
    } 
} 

static int foo2(const char *x) { 
    return x[0] + x[1]; 
} 

template <int (*F)(const char*)> 
void baz(const char *p) { 
    F(p); 
} 

int main() { 
    baz<foo>("ab"); // OK 
    baz<foo2>("ab"); // not valid 
} 
+0

Sí, pero ¿eso realmente está mejorando las cosas? Más tipeo, más paréntesis para equilibrar ... –

+4

@kotlinksi: Bueno, usted fue quien dijo que era un problema de legibilidad que solo haya tecleado 'namespace {}' una vez en varias pantallas de código. Ahora está diciendo que escribir es más un problema de escritura más de una vez.Si puede administrar el uso de funciones con enlace interno, entonces puede usar 'static'. Si por alguna razón necesitas funciones con enlaces externos, entonces realmente no importa cuáles son las ventajas de 'static ', porque no puedes tenerlas. –

+0

@kotlinksy: Supongo que otra posibilidad sería crear un archivo de encabezado solo para estas funciones. Dale un nombre que indique que todos sus contenidos están en el espacio de nombres sin nombre, y luego puedes decir dónde están las funciones según el archivo en el que se encuentran. –

1

Un espacio de nombres en el anonimato es la única cosa que no permite una declaración de clase contamina el ámbito global. Muy útil al definir una clase en un archivo .cpp.

2

Aparte de los puntos muy válidos señaladas por Steve que ver otros aspectos muy importantes en los espacios de nombres anónimos que hacen superiores a las funciones estáticas: Localidad, facilidad de refactorización y la ocultación de la información.

Supongamos que tiene una o dos funciones de clase que requieren varias otras funciones de ayuda que son bastante específicas pero no usan miembros de clase. Si te quedas con Robert C. Martin (las funciones deben ser pequeñas y tienen un propósito bien definido), a menudo encontrarás que las funciones grandes pueden refactorizarse en otras más pequeñas, aunque estas más pequeñas al principio solo se podrían usar en la antigua función principal.

Entonces, ¿qué opciones usted tiene:

  1. hacer una nueva clase (quizá privada) inmediatamente:

    Esto implica un buen montón de tipificación podría ser excesiva y -Permite enfrentan IT- todo el mundo a veces es flojo o tiene prisa.

  2. Generar eventos privados estáticas o funciones que no son miembros:

    Tanto implica editar el archivo de cabecera y el archivo CPP si lo hace adecuadamente, por lo que sigue siendo un poco carga que puedan interrumpir su flujo de trabajo más de lo necesario y genera código que innecesariamente desordena su archivo de encabezado, puede ser necesario enviar declaraciones o incluso incluye adicional en su encabezado.

  3. Anónimo espacio de nombres:

    Usted tiene una función de ayuda que no necesita acceso de miembros y sirve un propósito -> lo puso allí y escribir esta función cerca de los métodos de la clase en la que se utilizará . Esto es por mucho mi preferido: es rápido y no satura el archivo de encabezado. El espacio de nombre indica claramente: esto no es utilizado por nada más que este cpp. No amigo lo usará y ningún usuario de la biblioteca conocerá su existencia. Usted difícilmente puede ser más obvio y, a menudo este paradigma dará lugar a diseño de la función de limpieza que es de pocos parámetros de entrada y solo una salida modificada. Además, tiene la localidad de la función: definir justo antes del uso primario . Si bien esto podría ser un inconveniente, me resulta bastante útil cuando navego por las implementaciones de clases grandes. Otra ventaja son las constantes que abarcan varias funciones de , pero no son realmente interesantes para un usuario de la biblioteca. Póngalos en el espacio de nombres también, mejor en lo mismo con las funciones que los utilizan. Si sale después de que necesite las constantes y las funciones en otro lugar, transforme el en una clase, ya está empaquetado cuidadosamente.

Descargo de responsabilidad: Muchas personas podrían argumentar que el uso de un pimpl es mucho más limpio. Esta es solo mi opinión personal.

Cuestiones relacionadas