Criação de um namespace C ++ no cabeçalho e na fonte (cpp)

88

Existe alguma diferença entre envolver os conteúdos do arquivo de cabeçalho e cpp em um namespace ou envolver apenas o conteúdo do cabeçalho e, em seguida, usar o namespace no arquivo cpp?

Por diferença, quero dizer qualquer penalidade de desempenho de classificação ou semântica ligeiramente diferente que pode causar problemas ou qualquer coisa que eu preciso estar ciente.

Exemplo:

// header
namespace X
{
  class Foo
  {
  public:
    void TheFunc();
  };
}

// cpp
namespace X
{
  void Foo::TheFunc()
  {
    return;
  }
}

VS

// header
namespace X
{
  class Foo
  {
  public:
    void TheFunc();
  };
}

// cpp
using namespace X;
{
  void Foo::TheFunc()
  {
    return;
  }
} 

Se não houver diferença, qual é a forma preferida e por quê?

links77
fonte

Respostas:

37

O namespace é apenas uma maneira de destruir a assinatura da função para que não entrem em conflito. Alguns preferem a primeira forma e outros preferem a segunda versão. Ambas as versões não afetam o desempenho do tempo de compilação. Observe que os namespaces são apenas uma entidade de tempo de compilação.

O único problema que surge com o uso de namespace é quando temos os mesmos nomes de namespace aninhados (ou seja) X::X::Foo. Fazer isso cria mais confusão com ou sem o uso de palavras-chave.

vprajan
fonte
55

A diferença em "namespace X" para "using namespace X" está na primeira qualquer declaração nova estará sob o namespace, enquanto na segunda não.

No seu exemplo, não há nenhuma declaração nova - portanto, nenhuma diferença, portanto, nenhuma forma preferida.

Roee Gavirel
fonte
Depende do projeto e do estilo. Freqüentemente, há um namespace principal para uma carga de arquivos em um módulo, e o segundo estilo faz sentido.
Nicholas Wilson
8

Não há penalidades de desempenho, já que o resultado poderia ser o mesmo, mas colocar seu Foono namespace implicitamente introduz ambigüidade no caso de você ter Foos em namespaces diferentes. Você pode obter seu código fubar, de fato. Eu recomendo evitar o uso usingpara essa finalidade.

E você tem um perdido {depois using namespace;-)

Michael Krelin - hacker
fonte
Eu não chamaria de errante, pois corresponde ao fechamento } no final. No entanto, eu diria que esse par de
colchetes é
@blubberdiblub, a questão foi editado, se verificou a versão original, você poderia chamá-lo desviar ;-)
Michael Krelin - hacker de
1

Se o segundo compilar também, não deve haver diferenças. Os namespaces são processados ​​em tempo de compilação e não devem afetar as ações de tempo de execução.

Mas para questões de design, o segundo é horrível. Mesmo se ele compilar (não tenho certeza), não faz nenhum sentido.

holgac
fonte
1
Eu não acho que ele compila, mas não porque há uma diferença, mas porque há um perdido {;-)
Michael Krelin - hacker
A diferença é Foo :: TheFunc () é declarado no namespace global, enquanto é definido no namespace X.
bert-jan
1

O Foo :: TheFunc () não está no namespace correto no caso do VS. Use 'void X :: Foo :: TheFunc () {}' para implementar a função no namespace correto (X).

bert-jan
fonte
A pergunta é um pouco velha, mas você sabe quais são as consequências disso? ou seja, você terá problemas com a maneira como o caso do VS declara as funções no namespace, mas as define fora dele?
Adam Goodwin
1

No caso, se você envolver apenas o conteúdo .h, você terá que escrever usando o namespace ... no arquivo cpp, caso contrário, você sempre trabalhará no namespace válido. Normalmente, você agrupa os arquivos .cpp e .h, caso contrário, você corre o risco de usar objetos de outro namespace, o que pode gerar muitos problemas.

AlexTheo
fonte
0

Acho que a coisa certa a fazer aqui é usar o namespace para o escopo.

namespace catagory
{
    enum status
    {
      none,
      active,
      paused
    }
};

void func()
{
    catagory::status status;
    status = category::active;
}
Kjetil Hvalstrand
fonte
0

Se você está tentando usar variáveis ​​de uma para outra, recomendo externalizá-las e inicializá-las no arquivo de origem da seguinte forma:

// [.hh]
namespace example
{
   extern int a, b, c;
}
// [.cc]
// Include your header, then init the vars:
namespace example
{
   int a, b, c;
}
// Then in the function below, you can init them as what you want: 
void reference
{
    example::a = 0;
}

fonte