Considere um par de dois arquivos de origem: um arquivo de declaração de interface ( *.h
ou *.hpp
) e seu arquivo de implementação ( *.cpp
).
Deixe o *.h
arquivo ser assim:
namespace MyNamespace {
class MyClass {
public:
int foo();
};
}
Eu vi duas práticas diferentes para usar namespaces em arquivos de origem:
*.cpp
mostrando a prática nº 1:
#include "MyClass.h"
using namespace MyNamespace;
int MyClass::foo() { ... }
*.cpp
mostrando a prática 2:
#include "MyClass.h"
namespace MyNamespace {
int MyClass::foo() { ... }
}
Minha pergunta: há alguma diferença entre essas duas práticas e uma é considerada melhor do que a outra?
c++
namespaces
header-files
Nickolay
fonte
fonte
int MyNamespace::MyClass::foo() ...
.Respostas:
Do ponto de vista da legibilidade do código, provavelmente é melhor na minha opinião usar o método # 2 por este motivo:
Você pode ter
using
vários namespaces de uma vez, e qualquer objeto ou função escrito abaixo dessa linha pode pertencer a qualquer um desses namespaces (exceto conflitos de nomenclatura). Empacotar todo o arquivo em umnamespace
bloco é mais explícito e permite que você declare novas funções e variáveis que pertencem a esse namespace dentro do arquivo .cpp tambémfonte
O mais claro é a opção que você não mostrou:
int MyNamespace::MyClass::foo() { // ... }
Também é muito prolixo; demais para a maioria das pessoas. Como
using namespace
é um recurso para conflitos de nomes, pelo menos na minha experiência, e deve ser evitado, exceto em locais e escopos muito limitados, geralmente uso o seu # 2.fonte
Sim. # 1 e # 2 são exemplos de uma diretiva de uso e uma definição de namespace, respectivamente. Eles são efetivamente os mesmos neste caso, mas têm outras consequências. Por exemplo, se você introduzir um novo identificador ao lado
MyClass::foo
, ele terá um escopo diferente:# 1:
using namespace MyNamespace; int x; // defines ::x
# 2:
namespace MyNamespace { int x; // defines MyNamespace::x }
# 1 Prós: um pouco mais conciso; mais difícil introduzir algo acidentalmente
MyNamespace
sem querer. Contras: pode obter identificadores existentes de forma não intencional.# 2 Prós: mais claro que definições de identificadores existentes e declarações de novos identificadores pertencem
MyNamespace
. Contras: é mais fácil introduzir identificadores involuntariamenteMyNamespace
.Uma crítica tanto ao nº 1 quanto ao nº 2 é que eles estão se referindo a um namespace inteiro quando você provavelmente só se preocupa com a definição dos membros de
MyNamespace::MyClass
. Isso é pesado e comunica mal a intenção.Uma possível alternativa ao nº 1 é uma declaração de uso que inclui apenas o identificador no qual você está interessado:
#include "MyClass.h" using MyNamespace::MyClass; int MyClass::foo() { ... }
fonte
Também gostaria de acrescentar que, se por algum motivo você decidir implementar uma especialização de modelo em um arquivo cpp e confiar apenas em
using namespace
você, terá o seguinte problema:// .h file namespace someNameSpace { template<typename T> class Demo { void foo(); }; } // .cpp file using namespace someNameSpace; template<typename T> void Demo<T>::foo(){} // this will produce // error: specialization of 'template<class T> void someNameSpace::Demo<T>::foo()' in different namespace [-fpermissive] template<> void Demo<int>::foo(){}
Caso contrário, se você aplicar o método # 2, estará tudo bem.
fonte
Eu gostaria de adicionar mais uma maneira, usando a declaração de uso :
#include "MyClass.h" using MyNamespace::MyClass; int MyClass::foo() { ... }
Desta forma evita que você digite o nome do namespace muito tempo se a classe tiver muitas funções
fonte