Eu venho de um plano de fundo Java, onde pacotes são usados, não espaços para nome. Estou acostumado a reunir classes que trabalham juntas para formar um objeto completo em pacotes e, em seguida, reutilizá-las posteriormente a partir desse pacote. Mas agora estou trabalhando em C ++.
Como você usa namespaces em C ++? Você cria um único espaço para nome para o aplicativo inteiro ou para os principais componentes? Em caso afirmativo, como você cria objetos de classes em outros namespaces?
fonte
std
espaço de nomes para os símbolos do que usarusing
. Então, eu sempre escrevostd::cout
oustd::string
agora, porque é assim que eu os chamo agora. Eu nunca escreveriacout
.std
, eu pessoalmente achei isso muito menos importante quando você lida com bibliotecas menores. Geralmente, você pode usarusing namespace FooBario;
, principalmente se estiver usando um número considerável de tipos de uma biblioteca.using namespace X;
deve ser evitado nos arquivos de cabeçalho, se possível.mylibrary::endl
representar minha própria sequência de nova linha especial. Quero dizer, por que inventar nomes?Para evitar dizer tudo, Mark Ingram já disse uma pequena dica para usar namespaces:
Evite a diretiva "using namespace" nos arquivos de cabeçalho - isso abre o namespace para todas as partes do programa que importam esse arquivo de cabeçalho. Nos arquivos de implementação (* .cpp), isso normalmente não é um grande problema - embora eu prefira usar a diretiva "using namespace" no nível da função.
Acho que os namespaces são usados principalmente para evitar conflitos de nomes - não necessariamente para organizar sua estrutura de código. Eu organizaria programas em C ++ principalmente com arquivos de cabeçalho / estrutura de arquivos.
Às vezes, os namespaces são usados em projetos C ++ maiores para ocultar os detalhes da implementação.
Nota adicional à diretiva using: Algumas pessoas preferem usar "using" apenas para elementos únicos:
fonte
using std::cout;
é uma declaração usandousing std::cout, std::endl;
ou mesmousing std::cout, endl;
.using namespace x
em um cabeçalho se estiver em outro espaço para nome. Não é algo que eu recomendaria em geral, mas não polui o espaço para nome global.Vincent Robert está certo em seu comentário Como você usa corretamente os namespaces em C ++? .
Usando espaço para nome
Os espaços para nome são usados no mínimo para ajudar a evitar a colisão de nomes. Em Java, isso é imposto pelo idioma "org.domain" (porque supõe-se que não se use nada além de seu próprio nome de domínio).
No C ++, você pode atribuir um espaço para nome a todo o código do seu módulo. Por exemplo, para um módulo MyModule.dll, você pode atribuir ao código o espaço para nome MyModule. Eu já vi alguém usando MyCompany :: MyProject :: MyModule. Eu acho que isso é um exagero, mas apesar de tudo, parece correto para mim.
Usando "usando"
O uso deve ser usado com muito cuidado, pois importa efetivamente um (ou todos) símbolos de um espaço para nome no seu espaço para nome atual.
É ruim fazer isso em um arquivo de cabeçalho, porque seu cabeçalho poluirá todas as fontes, inclusive (ele me lembra macros ...) e, mesmo em um arquivo de origem, um estilo ruim fora do escopo de uma função, porque importará no escopo global os símbolos do espaço para nome.
A maneira mais segura de usar "using" é importar símbolos selecionados:
Você verá muitos "using namespace std;" no tutorial ou códigos de exemplo. O motivo é reduzir o número de símbolos para facilitar a leitura, não porque é uma boa ideia.
"using namespace std;" é desencorajado por Scott Meyers (não me lembro exatamente de qual livro, mas posso encontrá-lo, se necessário).
Composição do namespace
Namespaces são mais que pacotes. Outro exemplo pode ser encontrado na "The C ++ Programming Language" de Bjarne Stroustrup.
Na "Edição Especial", na 8.2.8 Composição do Espaço para Nome , ele descreve como você pode mesclar dois espaços para nome AAA e BBB em outro chamado CCC. Assim, o CCC se torna um alias para AAA e BBB:
Você pode até importar símbolos selecionados de diferentes espaços para nome, para criar sua própria interface de espaço para nome personalizado. Ainda não encontrei um uso prático disso, mas, em teoria, é legal.
fonte
Não vi nenhuma menção nas outras respostas, então aqui estão meus 2 centavos canadenses:
No tópico "usando espaço para nome", uma declaração útil é o alias do espaço para nome, permitindo que você "renomeie" um espaço para nome, normalmente para dar um nome mais curto. Por exemplo, em vez de:
você pode escrever:
fonte
Não dê ouvidos a todas as pessoas dizendo que espaços para nome são apenas espaços para nome.
Eles são importantes porque são considerados pelo compilador para aplicar o princípio da interface. Basicamente, isso pode ser explicado por um exemplo:
Se você quisesse imprimir um objeto A, o código seria este:
Observe que não mencionamos explicitamente o espaço para nome ao chamar a função. Este é o princípio da interface: o C ++ considera uma função que aceita um tipo como argumento como parte da interface desse tipo; portanto, não é necessário especificar o espaço para nome porque o parâmetro já implicava no espaço para nome.
Agora, por que esse princípio é importante? Imagine que o autor da classe A não forneceu uma função print () para esta classe. Você terá que fornecer um você mesmo. Como você é um bom programador, você definirá essa função em seu próprio espaço para nome, ou talvez no espaço para nome global.
E seu código pode começar a chamar a função de impressão (a) onde quiser. Agora imagine que anos depois, o autor decida fornecer uma função print (), melhor que a sua, porque conhece os aspectos internos da classe e pode criar uma versão melhor que a sua.
Os autores do C ++ decidiram que sua versão da função print () deveria ser usada em vez da fornecida em outro espaço de nome, para respeitar o princípio da interface. E que esse "upgrade" da função print () deve ser o mais fácil possível, o que significa que você não precisará alterar todas as chamadas para a função print (). É por isso que "funções de interface" (função no mesmo espaço para nome de uma classe) podem ser chamadas sem especificar o espaço para nome no C ++.
E é por isso que você deve considerar um namespace C ++ como uma "interface" ao usar um e ter em mente o princípio da interface.
Se você deseja uma melhor explicação desse comportamento, consulte o livro Excepcional C ++ de Herb Sutter
fonte
Na verdade, o boost usa toneladas de namespaces, normalmente cada parte do boost possui seu próprio espaço para o funcionamento interno e, em seguida, pode colocar apenas a interface pública no aumento do namespace de nível superior.
Pessoalmente, acho que quanto maior a base de código se tornar, mais os espaços de nome se tornarão, mesmo em um único aplicativo (ou biblioteca). No trabalho, colocamos cada módulo de nosso aplicativo em seu próprio espaço para nome.
Outro uso (sem trocadilhos) de namespaces que eu uso muito é o namespace anônimo:
É basicamente o mesmo que:
Usar um espaço para nome anônimo (em vez de estático) é, no entanto, a maneira recomendada de código e dados ficarem visíveis apenas na unidade de compilação atual em C ++.
fonte
const int CONSTANT = 42;
porque a const de nível superior em um escopo de espaço para nome já implica em ligação interna. Portanto, você não precisa do espaço para nome anônimo neste caso.Além disso, observe que você pode adicionar a um espaço para nome. Isso é mais claro com um exemplo, o que quero dizer é que você pode ter:
em um arquivo
square.h
eem um arquivo
cube.h
. Isso define um único espaço para nomeMyNamespace
(ou seja, você pode definir um único espaço para nome em vários arquivos).fonte
Em Java:
Em C ++:
E usando-os, Java:
E C ++:
Além disso, os nomes completos são "somepackge.SomeClass" para Java e "somenamespace :: SomeClass" para C ++. Usando essas convenções, você pode organizar como está acostumado em Java, incluindo a criação de nomes de pastas correspondentes para namespaces. Os requisitos de pasta-> pacote e arquivo-> classe ainda não existem, portanto, você pode nomear suas pastas e classes independentemente dos pacotes e espaços para nome.
fonte
@ marius
Sim, você pode usar vários espaços para nome por vez, por exemplo:
[Fevereiro 2014 - (Realmente faz tanto tempo?): Este exemplo em particular agora é ambíguo, como Joey aponta abaixo. Boost e std :: agora cada um tem um shared_ptr.]
fonte
std
também já existeshared_ptr
, portanto, o uso de namespacesboost
e de ambosstd
entrará em conflito ao tentar usar ashared_ptr
.Você também pode conter "using namespace ..." dentro de uma função, por exemplo:
fonte
De um modo geral, crio um espaço para nome de um corpo de código, se acredito que possa haver conflitos de nome de função ou tipo com outras bibliotecas. Também ajuda a codificar a marca, ala boost :: .
fonte
Prefiro usar um namespace de nível superior para o aplicativo e sub namespaces para os componentes.
A maneira como você pode usar classes de outros namespaces é surpreendentemente muito semelhante à maneira em java. Você pode usar "use NAMESPACE", que é semelhante a uma instrução "import PACKAGE", por exemplo, use std. Ou você especifica o pacote como prefixo da classe separado por "::", por exemplo, std :: string. Isso é semelhante ao "java.lang.String" em Java.
fonte
Observe que um espaço para nome em C ++ realmente é apenas um espaço para nome. Eles não fornecem o encapsulamento que os pacotes fornecem em Java, portanto você provavelmente não os utilizará tanto.
fonte
Eu usei namespaces C ++ da mesma maneira que em C #, Perl, etc. É apenas uma separação semântica de símbolos entre itens de biblioteca padrão, itens de terceiros e meu próprio código. Eu colocaria meu próprio aplicativo em um espaço para nome e, em seguida, um componente de biblioteca reutilizável em outro espaço para nome para separação.
fonte
Outra diferença entre java e C ++, é que, em C ++, a hierarquia de namespaces não precisa maquinar o layout do sistema de arquivos. Portanto, costumo colocar uma biblioteca reutilizável inteira em um único espaço para nome e subsistemas dentro da biblioteca em subdiretórios:
Eu só colocaria os subsistemas em namespaces aninhados se houvesse a possibilidade de um conflito de nomes.
fonte