Troquei de C ++ para Java e C # e acho que o uso de namespaces / pacotes é muito melhor lá (bem estruturado). Então voltei para o C ++ e tentei usar namespaces da mesma maneira, mas a sintaxe necessária é horrível no arquivo de cabeçalho.
namespace MyCompany
{
namespace MyModule
{
namespace MyModulePart //e.g. Input
{
namespace MySubModulePart
{
namespace ...
{
public class MyClass
O seguinte parece estranho para mim também (para evitar o recuo profundo):
namespace MyCompany
{
namespace MyModule
{
namespace MyModulePart //e.g. Input
{
namespace MySubModulePart
{
namespace ...
{
public class MyClass
{
Existe uma maneira mais curta de expressar a coisa acima? Estou perdendo algo como
namespace MyCompany::MyModule::MyModulePart::...
{
public class MyClass
Atualizar
Ok, alguns dizem que o conceito de uso em Java / C # e C ++ é diferente. Realmente? Eu acho que o carregamento de classe (dinâmico) não é o único propósito para namespaces (esta é uma perspectiva muito técnica). Por que não devo usá-lo para uma legibilidade e estruturação, por exemplo, pense em "IntelliSense".
Atualmente, não há lógica / ligação entre um namespace e o que você pode encontrar nele. Java e C # fazem isso muito melhor ... Por que incluir <iostream>
e ter namespace std
? Ok, se você diz que a lógica deve depender do cabeçalho a ser incluído, por que o #include não usa uma sintaxe amigável "IntelliSense" como #include <std::io::stream>
ou <std/io/stream>
? Acho que a estruturação ausente nas bibliotecas padrão é um ponto fraco do C ++ em comparação com Java / C #.
Se a exclusividade para conflitos ávidos é um ponto (que é um ponto de C # e Java também), uma boa ideia é usar o nome do projeto ou o nome da empresa como namespace, você não acha?
Por um lado, diz-se que C ++ é o mais flexível ... mas todos disseram "não faça isso"? Parece-me que C ++ pode fazer muitas coisas, mas tem uma sintaxe horrível até mesmo para as coisas mais fáceis em muitos casos, em comparação com C #.
Atualização 2
A maioria dos usuários diz que é um absurdo criar um aninhamento mais profundo do que dois níveis. Ok, então o que dizer dos namespaces Windows :: UI :: Xaml e Windows :: UI :: Xaml :: Controls :: Primitives no desenvolvimento do Win8? Acho que o uso de namespaces pela Microsoft faz sentido e é mais profundo do que apenas 2 níveis. Acho que bibliotecas / projetos maiores precisam de um aninhamento mais profundo (odeio nomes de classes como ExtraLongClassNameBecauseEveryThingIsInTheSameNameSpace ... então você poderia colocar tudo no namespace global também.)
Atualização 3 - Conclusão
A maioria diz "não faça isso", mas ... mesmo o boost tem um aninhamento mais profundo do que um ou dois níveis. Sim, é uma biblioteca, mas: Se você deseja código reutilizável - trate seu próprio código como uma biblioteca que você daria a outra pessoa. Eu também uso um aninhamento mais profundo para fins de descoberta usando namespaces.
fonte
namespace
palavra-chave?Respostas:
C ++ 17 pode simplificar a definição de namespace aninhado:
é equivalente a
Consulte (8) na página do namespace em cppreference:
http://en.cppreference.com/w/cpp/language/namespace
fonte
/std:c++latest
/std:c++latest
no Visual Studio 2015 e também usar Boost, poderá encontrar erros de compilador muito místicos ao incluir alguns cabeçalhos Boost. Enfrentei esse problema conforme descrito nesta pergunta StackOverflowPara evitar recuos realmente profundos, geralmente faço desta forma:
fonte
clang-format
não pode formatar isso, pois você mostra clang.llvm.org/docs/ClangFormatStyleOptions.html (NamespaceIndentation)Apoio totalmente a resposta de Peterchen, mas gostaria de acrescentar algo que responda a outra parte de sua pergunta.
Declarar namespaces é um dos casos muito raros em C ++ em que realmente gosto do uso de
#define
s.Isso também elimina a necessidade de comentários próximos à chave de fechamento do namespace (você já rolou para baixo até o final de um arquivo de origem grande e tentou adicionar / remover / balancear chaves que estavam faltando comentários sobre qual chave fecha qual escopo? Não é divertido .).
Se você quiser colocar todas as declarações de namespace em uma única linha, também pode fazer isso com um pouco da mágica do pré-processador (muito feia):
Agora você pode fazer isso:
Para aninhar mais de três níveis, você teria que adicionar macros auxiliares até a contagem desejada.
fonte
#define
goste, estou bastante impressionado com a mágica do pré-processador ... apenas se eu não precisar adicionar macros auxiliares adicionais para aninhamento mais profundo ... bem, não vou usá-lo de qualquer maneira .. .Os namespaces C ++ são usados para agrupar interfaces, não para dividir componentes ou expressar divisão política.
O padrão se esforça para proibir o uso de namespaces como o Java. Por exemplo, apelidos de namespace fornecem uma maneira de usar nomes de namespace longos ou profundamente aninhados.
Mas
namespace nsc {}
então seria um erro, porque um namespace só pode ser definido usando seu nome de namespace original . Essencialmente, o padrão facilita as coisas para o usuário de tal biblioteca, mas difícil para o implementador . Isso desencoraja as pessoas de escrever tais coisas, mas atenua os efeitos se o fizerem.Você deve ter um namespace por interface definido por um conjunto de classes e funções relacionadas. Subinterfaces internas ou opcionais podem entrar em namespaces aninhados. Mas mais de dois níveis de profundidade deve ser uma bandeira vermelha muito séria.
Considere o uso de caracteres de sublinhado e prefixos de identificador onde o
::
operador não é necessário.fonte
company::division
overcompany_division
?Não, e por favor, não faça isso.
O objetivo dos namespaces é principalmente resolver conflitos no namespace global.
Um propósito secundário é a abreviação local de símbolos; por exemplo, um
UpdateUI
método complexo pode usar umusing namespace WndUI
para usar símbolos mais curtos.Estou em um projeto 1.3MLoc e os únicos namespaces que temos são:
#import
e#include windows.h
)ModuleDetailHereBeTygers
namespaces em libs apenas de cabeçalho)Neste projeto, nomes de classes etc. usam um código de "região" de duas ou três letras (por exemplo, em
CDBNode
vez deDB::CNode
). Se você preferir o último, há espaço para um segundo nível de namespaces "públicos", mas não mais.Enums específicos de classe etc. podem ser membros dessas classes (embora eu concorde que isso nem sempre é bom e às vezes é difícil dizer se você deve)
Raramente há necessidade de um namespace de "empresa", exceto se você estiver tendo grandes problemas com bibliotecas de terceiros que são distribuídas como binárias, não fornecem seu próprio namespace e não podem ser facilmente colocadas em um (por exemplo, em um binário distribuição). Ainda assim, na minha experiência, forçá- los a um namespace é muito mais fácil de fazer.
[editar] De acordo com a pergunta de acompanhamento de Stegi:
Desculpe se não fui claro o suficiente: dois níveis não é um limite rígido e mais não é intrinsecamente ruim. Eu só queria salientar que raramente você precisa de mais de dois, por experiência própria, mesmo em uma grande base de código. Aninhar mais fundo ou mais superficial é uma troca.
Agora, o caso da Microsoft é indiscutivelmente diferente. Presumivelmente, uma equipe muito maior e todo o código é uma biblioteca.
Eu presumo que a Microsoft está imitando aqui o sucesso da Biblioteca .NET, onde os namespaces contribuem para a descoberta da extensa biblioteca. (.NET tem cerca de 18.000 tipos.)
Além disso, eu assumiria que existe uma (ordem de magnitude) de símbolos ideais em um namespace. digamos, 1 não faz sentido, 100 parece certo, 10000 é claramente muito.
TL; DR: É uma troca e não temos números concretos. Jogue pelo seguro, não exagere em nenhuma direção. O "Não faça isso" vem meramente do "Você tem problemas com isso, eu teria problemas com isso e não vejo uma razão para que você precise".
fonte
Constants
, a seguir, criar namespaces aninhados com nomes apropriados para categorizar as constantes; se necessário, uso mais namespaces para evitar colisões de nomes. EsteConstants
namespace está contido em um namespace pega-tudo para o código do sistema do programa, com um nome comoSysData
. Isto cria um nome completo contendo três ou quatro espaços de nome (tal comoSysData::Constants::ErrorMessages
,SysData::Constants::Ailments::Bitflags
, ouSysData::Defaults::Engine::TextSystem
).using
diretiva para trazer os nomes apropriados, minimizando a possibilidade de nomes conflitantes. Acho que melhora a legibilidade e ajuda a documentar as dependências de qualquer bloco de código. Além das constantes, tenho tendência a tentar mantê-lo em dois namespaces, se possível (comoSysData::Exceptions
eSysData::Classes
).Aqui está uma citação de documentos Lzz (Lazy C ++):
Claro que a qualidade das fontes que dependem de tais ferramentas é discutível ... Eu diria que é mais uma curiosidade, mostrando que a doença de sintaxe induzida por C ++ pode assumir várias formas (eu também tenho a minha ...)
fonte
Ambos os padrões (C ++ 2003 e C ++ 11) são muito explícitos de que o nome do namespace é um identificador. Isso significa que cabeçalhos aninhados explícitos são necessários.
Minha impressão é que não é grande coisa permitir a colocação de um identificador qualificado ao lado de um simples nome do namespace, mas por algum motivo isso não é permitido.
fonte
Você pode usar esta sintaxe:
Observe que essa sintaxe é válida mesmo em C ++ 98 e é quase semelhante ao que está agora disponível em C ++ 17 com definições de namespace aninhadas .
Feliz desaninhamento!
Fontes:
fonte
Este artigo cobre o assunto muito bem: Documento de namespace
O que basicamente se resume a isso. Quanto mais longos forem os seus namespaces, maior será a probabilidade de as pessoas usarem o
using namespace
diretiva.Então, olhando para o código a seguir, você pode ver um exemplo em que isso irá prejudicá-lo:
Este código irá compilar bem, no entanto, se você descomentar a linha
//using namespace def;
, o namespace de "teste" se tornará ambíguo e você terá conflitos de nomenclatura. Isso significa que sua base de código pode ir de estável para instável incluindo uma biblioteca de terceiros.Em C #, mesmo que você use
using abc;
eusing def;
o compilador seja capaz de reconhecer issotesting::myClass
ou mesmo apenasmyClass
esteja noabc::testing
namespace, mas C ++ não reconhecerá isso e será detectado como uma colisão.fonte
Sim, você terá que fazer como
No entanto, você está tentando usar os namespaces de uma maneira que eles não deveriam ser usados. Verifique esta questão, talvez você a considere útil.
fonte
[EDIT:]
Desde c ++ 17 namespaces aninhados são suportados como um recurso de linguagem padrão ( https://en.wikipedia.org/wiki/C%2B%2B17 ). A partir de agora, esse recurso não é compatível com g ++ 8, mas pode ser encontrado no compilador clang ++ 6.0.
[CONCLUSÃO:]
Use
clang++6.0 -std=c++17
como seu comando de compilação padrão. Então, tudo deve funcionar bem - e você poderá compilar comnamespace OuterNS::InnerNS1::InnerNS2 { ... }
seus arquivos.[RESPOSTA ORIGINAL:]
Como esta pergunta é um pouco antiga, presumo que você mudou. Mas para outros, que ainda estão procurando uma resposta, tive a seguinte ideia:
(Posso fazer um anúncio do Emacs aqui :)?) Postar uma imagem é muito mais fácil e mais legível do que simplesmente postar o código. Não pretendo fornecer uma resposta completa de todos os casos esquivos, simplesmente pretendia dar alguma inspiração. (Eu apoio totalmente C # e sinto que em muitos casos C ++ deve adotar alguns recursos OOP, já que C # é popular principalmente devido à sua facilidade de uso comparada).
fonte