Cambié de C ++ a Java y C # y creo que el uso de espacios de nombres / paquetes es mucho mejor allí (bien estructurado). Luego volví a C ++ e intenté usar los espacios de nombres de la misma manera, pero la sintaxis requerida es horrible dentro del archivo de encabezado.
namespace MyCompany
{
namespace MyModule
{
namespace MyModulePart //e.g. Input
{
namespace MySubModulePart
{
namespace ...
{
public class MyClass
Lo siguiente también me parece extraño (para evitar la sangría profunda):
namespace MyCompany
{
namespace MyModule
{
namespace MyModulePart //e.g. Input
{
namespace MySubModulePart
{
namespace ...
{
public class MyClass
{
¿Existe una forma más corta de expresar lo anterior? Me falta algo como
namespace MyCompany::MyModule::MyModulePart::...
{
public class MyClass
Actualizar
Ok, algunos dicen que el concepto de uso en Java / C # y C ++ es diferente. De Verdad? Creo que la carga de clases (dinámica) no es el único propósito de los espacios de nombres (esta es una perspectiva razonada muy técnica). ¿Por qué no debería usarlo para una legibilidad y estructuración, por ejemplo, pensar en "IntelliSense"?
Actualmente, no hay lógica / pegamento entre un espacio de nombres y lo que puede encontrar allí. Java y C # hacen esto mucho mejor ... ¿Por qué incluir <iostream>
y tener espacio de nombres std
? Ok, si dices que la lógica debería depender del encabezado para incluir, ¿por qué #include no usa una sintaxis amigable con "IntelliSense" como #include <std::io::stream>
o <std/io/stream>
? Creo que la estructuración que falta en las bibliotecas predeterminadas es una debilidad de C ++ en comparación con Java / C #.
Si la exclusividad de los conflictos ávidos es un punto (que también es un punto de C # y Java), una buena idea es usar el nombre del proyecto o el nombre de la empresa como espacio de nombres, ¿no lo crees?
Por un lado, se dice que C ++ es el más flexible ... ¿pero todos dijeron "no hagas esto"? Me parece que C ++ puede hacer muchas cosas, pero tiene una sintaxis horrible incluso para las cosas más fáciles en muchos casos en comparación con C #.
Actualización 2
La mayoría de los usuarios dicen que no tiene sentido crear un anidamiento más profundo que dos niveles. Ok, ¿qué pasa con los espacios de nombres de Windows :: UI :: Xaml y Windows :: UI :: Xaml :: Controls :: Primitives en el desarrollo de Win8? Creo que el uso de espacios de nombres por parte de Microsoft tiene sentido y, de hecho, es más profundo que solo 2 niveles. Creo que las bibliotecas / proyectos más grandes necesitan un anidamiento más profundo (odio los nombres de clases como ExtraLongClassNameBecauseEveryThingIsInTheSameNameSpace ... entonces también podría poner todo en el espacio de nombres global).
Actualización 3 - Conclusión
La mayoría dice "no lo hagas", pero ... incluso el impulso tiene un anidamiento más profundo que uno o dos niveles. Sí, es una biblioteca, pero: si desea un código reutilizable, trate su propio código como una biblioteca que le daría a otra persona. También utilizo un anidamiento más profundo con fines de descubrimiento utilizando espacios de nombres.
fuente
namespace
palabras clave?Respuestas:
C ++ 17 podría simplificar la definición del espacio de nombres anidado:
es equivalente a
Consulte (8) en la página de espacio de nombres en cppreference:
http://en.cppreference.com/w/cpp/language/namespace
fuente
/std:c++latest
/std:c++latest
Visual Studio 2015 y también usa Boost, puede encontrar errores de compilador muy místicos cuando incluya algunos encabezados de Boost. Enfrenté este problema como se describe en esta pregunta de StackOverflowPara evitar una sangría realmente profunda, generalmente lo hago de esta manera:
fuente
clang-format
no puede formatear eso ya que muestra clang.llvm.org/docs/ClangFormatStyleOptions.html (NamespaceIndentation)Apoyo completamente la respuesta de Peterchen, pero quiero agregar algo que aborde otra parte de su pregunta.
La declaración de espacios de nombres es uno de los casos muy raros en C ++ en los que realmente me gusta el uso de
#define
s.Esto también elimina la necesidad de comentarios cerca de la llave de cierre del espacio de nombres (¿Alguna vez se desplazó hacia abajo hasta la parte inferior de un archivo fuente grande e intentó agregar / eliminar / equilibrar llaves a las que les faltaban comentarios sobre qué llave cierra qué alcance? No es divertido .).
Si desea poner todas las declaraciones de espacio de nombres en una sola línea, puede hacerlo también con un poco de magia de preprocesador (bastante fea):
Ahora puedes hacer esto:
Para anidar a más de tres niveles, tendría que agregar macros auxiliares hasta el recuento deseado.
fuente
#define
, estoy bastante impresionado con la magia del preprocesador ... solo si no tengo que agregar macros de ayuda adicionales para un anidamiento más profundo ... bueno, no lo voy a usar de todos modos, así que ... .Los espacios de nombres C ++ se utilizan para agrupar interfaces, no para dividir componentes o expresar división política.
El estándar hace todo lo posible para prohibir el uso de espacios de nombres similar al de Java. Por ejemplo, los alias de espacios de nombres proporcionan una forma de utilizar fácilmente nombres de espacios de nombres largos o profundamente anidados.
Pero
namespace nsc {}
entonces sería un error, porque un espacio de nombres solo se puede definir usando su nombre de espacio de nombres original . Básicamente, el estándar facilita las cosas para el usuario de una biblioteca de este tipo, pero dificulta al implementador . Esto desalienta a las personas a escribir tales cosas, pero mitiga los efectos si lo hacen.Debe tener un espacio de nombres por interfaz definido por un conjunto de clases y funciones relacionadas. Las subinterfaces internas u opcionales pueden entrar en espacios de nombres anidados. Pero más de dos niveles de profundidad debería ser una señal de alerta muy seria.
Considere la posibilidad de utilizar caracteres de subrayado y prefijos de identificador cuando
::
no se necesite el operador.fuente
company::division
overcompany_division
?No, y por favor no hagas eso.
El propósito de los espacios de nombres es principalmente resolver conflictos en el espacio de nombres global.
Un propósito secundario es la abreviatura local de símbolos; por ejemplo, un
UpdateUI
método complejo puede utilizar unusing namespace WndUI
para utilizar símbolos más cortos.Estoy en un proyecto 1.3MLoc, y los únicos espacios de nombres que tenemos son:
#import
y#include windows.h
)ModuleDetailHereBeTygers
nombres de "detalles de implementación" que no forman parte de la API pública (espacios de nombres anónimos en .cpp o espacios de nombres en bibliotecas de solo encabezado)En este proyecto, los nombres de clases, etc. utilizan un código de "región" de dos o tres letras (por ejemplo, en
CDBNode
lugar deDB::CNode
). Si prefiere lo último, hay espacio para un segundo nivel de espacios de nombres "públicos", pero no más.Las enumeraciones específicas de la clase, etc.pueden ser miembros de esas clases (aunque estoy de acuerdo en que esto no siempre es bueno, y a veces es difícil decir si debería hacerlo)
Rara vez es necesario un espacio de nombres de "empresa", excepto si tiene grandes problemas con bibliotecas de terceros que se distribuyen como binarias, no proporcionan su propio espacio de nombres y no se pueden poner fácilmente en uno (por ejemplo, en un binario distribución). Aún así, en mi experiencia, forzarlos a entrar en un espacio de nombres es mucho más fácil de hacer.
[editar] Según la pregunta de seguimiento de Stegi:
Lo siento si no fui lo suficientemente claro: dos niveles no es un límite estricto y más no es intrínsecamente malo. Solo quería señalar que rara vez se necesitan más de dos, según mi experiencia, incluso en una base de código grande. Anidar más profundo o menos profundo es una compensación.
Ahora, el caso de Microsoft es posiblemente diferente. Es de suponer que un equipo mucho más grande y todo el código es una biblioteca.
Asumiría que Microsoft está imitando aquí el éxito de la biblioteca .NET, donde los espacios de nombres contribuyen a la visibilidad de la extensa biblioteca. (.NET tiene alrededor de 18000 tipos).
Además, supongo que hay un símbolo óptimo (orden de magnitud de) en un espacio de nombres. digamos, 1 no tiene sentido, 100 suena bien, 10000 es claramente demasiado.
TL; DR: Es una compensación y no tenemos cifras concretas. Juega seguro, no exageres en ninguna dirección. El "No hagas eso" proviene simplemente del "Tienes problemas con eso, yo tendría problemas con eso y no veo una razón por la que lo necesites".
fuente
Constants
, luego crear espacios de nombres anidados con nombres apropiados para categorizar las constantes; si es necesario, utilizo más espacios de nombres para evitar colisiones de nombres. EsteConstants
espacio de nombres está contenido en un espacio de nombres general para el código del sistema del programa, con un nombre comoSysData
. Esto crea un nombre completo que contiene tres o cuatro espacios de nombres (comoSysData::Constants::ErrorMessages
,SysData::Constants::Ailments::Bitflags
, oSysData::Defaults::Engine::TextSystem
).using
directiva para traer los nombres apropiados, minimizando la posibilidad de conflictos de nombres. Encuentro que mejora la legibilidad y ayuda a documentar las dependencias de cualquier bloque de código. Aparte de las constantes, tiendo a intentar mantenerlo en dos espacios de nombres si es posible (comoSysData::Exceptions
ySysData::Classes
).Aquí una cita de los documentos de Lzz (Lazy C ++):
Por supuesto, la calidad de las fuentes que dependen de tales herramientas es discutible ... Yo diría que es más una curiosidad, mostrar que la enfermedad sintáctica inducida por C ++ puede tomar muchas formas (yo también tengo la mía ...)
fuente
Ambos estándares (C ++ 2003 y C ++ 11) son muy explícitos en cuanto a que el nombre del espacio de nombres es un identificador. Esto significa que se requieren encabezados anidados explícitos.
Mi impresión es que no es un gran problema permitir colocar un identificador calificado además de un nombre simple del espacio de nombres, pero por alguna razón esto no está permitido.
fuente
Puede utilizar esta sintaxis:
Tenga en cuenta que esta sintaxis es válida incluso en C ++ 98 y es casi similar a lo que ahora está disponible en C ++ 17 con definiciones de espacio de nombres anidadas .
¡Feliz desanidación!
Fuentes:
fuente
Este documento cubre bastante bien el tema: Papel de espacio de nombres
Lo que básicamente se reduce a esto. Cuanto más largos sean los espacios de nombres, más probabilidades habrá de que las personas utilicen la
using namespace
directiva.Entonces, mirando el siguiente código, puede ver un ejemplo en el que esto lo perjudicará:
Este código se compilará bien, sin embargo, si descomenta la línea
//using namespace def;
, el espacio de nombres de "prueba" se volverá ambiguo y tendrá colisiones de nombres. Esto significa que su base de código puede pasar de estable a inestable al incluir una biblioteca de terceros.En C #, incluso si lo usara
using abc;
yusing def;
el compilador fuera capaz de reconocerlotesting::myClass
o incluso solo estuvieramyClass
en elabc::testing
espacio de nombres, pero C ++ no reconocería esto y se detecta como una colisión.fuente
Si, tendrás que hacerlo como
Sin embargo, está intentando utilizar los espacios de nombres de una forma en que no se supone que se utilicen. Marque esta pregunta, tal vez la encuentre útil.
fuente
[EDITAR:]
Dado que los espacios de nombres anidados de c ++ 17 son compatibles como una característica de idioma estándar ( https://en.wikipedia.org/wiki/C%2B%2B17 ). A partir de ahora, esta función no es compatible con g ++ 8, pero se puede encontrar en el compilador clang ++ 6.0.
[CONCLUSIÓN:]
Úselo
clang++6.0 -std=c++17
como su comando de compilación predeterminado. Entonces todo debería funcionar bien y podrá compilarnamespace OuterNS::InnerNS1::InnerNS2 { ... }
en sus archivos.[RESPUESTA ORIGINAL:]
Dado que esta pregunta es un poco antigua, asumiré que ha seguido adelante. Pero para otros, que todavía están buscando una respuesta, se me ocurrió la siguiente idea:
(¿Puedo hacer un anuncio para Emacs aquí :)?) Publicar una imagen es mucho más fácil y más legible que simplemente publicar un código. No tengo la intención de proporcionar una respuesta completa de todos los casos de esquina, simplemente quise dar algo de inspiración. (Soy totalmente compatible con C # y creo que en muchos casos C ++ debería adoptar algunas características de programación orientada a objetos, ya que C # es popular principalmente debido a su facilidad de uso comparada).
fuente