c++ - use - what is namespace




Como você usa corretamente namespaces em C++? (10)

Eu venho de um fundo Java, onde os pacotes são usados, não os namespaces. Estou acostumado a colocar classes que funcionam juntas para formar um objeto completo em pacotes e, em seguida, reutilizá-los posteriormente a partir desse pacote. Mas agora estou trabalhando em C ++.

Como você usa namespaces em C ++? Você cria um único namespace para o aplicativo inteiro ou cria namespaces para os principais componentes? Em caso afirmativo, como você cria objetos de classes em outros namespaces?


Projetos maiores em C ++ que eu já vi dificilmente usaram mais de um namespace (por exemplo, biblioteca boost).

Na verdade, o boost usa muitos namespaces, normalmente cada parte do boost tem seu próprio namespace para o funcionamento interno e, em seguida, pode colocar apenas a interface pública no aumento do namespace de nível superior.

Pessoalmente, penso que quanto maior se torna uma base de código, mais importantes são os espaços de nomes, mesmo dentro de uma única aplicação (ou biblioteca). No trabalho, colocamos cada módulo de nossa aplicação em seu próprio namespace.

Outro uso (sem trocadilhos) de namespaces que eu uso muito é o namespace anônimo:

namespace {
  const int CONSTANT = 42;
}

Isso é basicamente o mesmo que:

static const int CONSTANT = 42;

No entanto, usar um namespace anônimo (em vez de estático) é a maneira recomendada de o código e os dados serem visíveis apenas na unidade de compilação atual em C ++.


@ below

Sim, você pode usar vários namespaces por vez, por exemplo:

using namespace boost;   
using namespace std;  

shared_ptr<int> p(new int(1));   // shared_ptr belongs to boost   
cout << "cout belongs to std::" << endl;   // cout and endl are in std

[Fev. 2014 - (Tem sido realmente tanto tempo assim?): Este exemplo em particular agora é ambíguo, como Joey aponta abaixo. Boost e std :: now têm um shared_ptr.]


De modo geral, eu crio um namespace para um corpo de código se eu acreditar que pode haver conflitos de nome de função ou tipo com outras bibliotecas. Também ajuda a codificar a marca, ala boost:: .


Em Java:

package somepackage;
class SomeClass {}

Em C ++:

namespace somenamespace {
    class SomeClass {}
}

E usando eles, Java:

import somepackage;

E C ++:

using namespace somenamespace;

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 criar nomes de pastas correspondentes para namespaces. Os requisitos de pasta-> pacote e arquivo-> classe não estão lá, então você pode nomear suas pastas e classes independentemente dos pacotes e namespaces.


Eu 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 a "java.lang.String" em Java.


Eu usei namespaces de C ++ da mesma maneira que eu faço em C #, Perl, etc. É apenas uma separação semântica de símbolos entre material de biblioteca padrão, material de terceiros e meu próprio código. Eu colocaria meu próprio aplicativo em um namespace e, em seguida, um componente de biblioteca reutilizável em outro namespace para separação.


Namespaces são pacotes essencialmente. Eles podem ser usados ​​assim:

namespace MyNamespace
{
  class MyClass
  {
  };
}

Então no código:

MyNamespace::MyClass* pClass = new MyNamespace::MyClass();

Espero que ajude.

Ou, se você quiser sempre usar um namespace específico, você pode fazer isso:

using namespace MyNamespace;

MyClass* pClass = new MyClass();

Edit: Seguindo o que bernhardrusch disse, eu costumo não usar a sintaxe "using namespace x", eu costumo especificar explicitamente o namespace ao instanciar meus objetos (ie o primeiro exemplo que mostrei).

E como você perguntou below , você pode usar quantos namespaces quiser.


Observe que um namespace em C ++ realmente é apenas um espaço de nome. Eles não fornecem nada do encapsulamento que os pacotes fazem em Java, então você provavelmente não os usará tanto.


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.

Eu acho que namespaces são usados ​​principalmente para evitar conflitos de nomenclatura - não necessariamente para organizar sua estrutura de código. Eu organizaria programas C ++ principalmente com arquivos de cabeçalho / estrutura de arquivos.

Às vezes, namespaces são usados ​​em projetos C ++ maiores para ocultar detalhes de implementação.

Nota adicional à diretiva using: Algumas pessoas preferem usar "using" apenas para elementos simples:

using std::cout;  
using std::endl;

Vincent Robert está certo em seu comentário Como você usa corretamente namespaces em C ++? .

Usando o namespace

Os namespaces são usados ​​no mínimo para ajudar a evitar colisões de nomes. Em Java, isso é imposto através do idioma "org.domain" (porque supõe-se que não se use nada além de seu próprio nome de domínio).

Em C ++, você poderia dar um namespace para todo o código em seu módulo. Por exemplo, para um módulo MyModule.dll, você poderia dar seu código ao namespace MyModule. Eu vi em outro lugar 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 porque ele efetivamente importa um (ou todos) os símbolos de um namespace para o seu namespace atual.

Isso é ruim para fazê-lo em um arquivo de cabeçalho porque o seu cabeçalho irá poluir todas as fontes, incluindo-o (me lembra de macros ...), e até mesmo em um arquivo de origem, mau estilo fora de um escopo de função porque ele importará no escopo global os símbolos do espaço de nomes.

A maneira mais segura de usar "usando" é importar símbolos de seleção:

void doSomething()
{
   using std::string ; // string is now "imported", at least,
                       // until the end of the function
   string a("Hello World!") ;
   std::cout << a << std::endl ;
}

void doSomethingElse()
{
   using namespace std ; // everything from std is now "imported", at least,
                       // until the end of the function
   string a("Hello World!") ;
   cout << a << endl ;
}

Você verá muito "usando namespace std;" em tutorial ou códigos de exemplo. O motivo é reduzir o número de símbolos para facilitar a leitura, não porque seja uma boa ideia.

"usando namespace std;" é desencorajado por Scott Meyers (não me lembro exatamente qual livro, mas posso encontrá-lo se necessário).

Composição do namespace

Namespaces são mais que pacotes. Outro exemplo pode ser encontrado em "The C ++ Programming Language", de Bjarne Stroustrup.

No "Special Edition", em 8.2.8 Namespace Composition , ele descreve como você pode mesclar dois namespaces AAA e BBB em outro chamado CCC. Assim, o CCC se torna um pseudônimo para AAA e BBB:

namespace AAA
{
   void doSomething() ;
}

namespace BBB
{
   void doSomethingElse() ;
}

namespace CCC
{
   using namespace AAA ;
   using namespace BBB ;
}

void doSomethingAgain()
{
   CCC::doSomething() ;
   CCC::doSomethingElse() ;
}

Você pode até importar símbolos de seleção de namespaces diferentes para criar sua própria interface de namespace personalizada. Eu ainda tenho que encontrar um uso prático disso, mas, em teoria, é legal.





namespaces