Namespaces
Considere o seguinte cenário: você está ajudando no desenvolvimento de um software de um painel digital para uma loja. O painel mostra mensagens de promoções primárias da loja e, agora, deseja-se adicionar um painel secundário para exibir promoções secundárias. Você foi designado a implementar uma função que toma como parâmetro uma mensagem e a mostra no display do novo painel. Para tal, você começa a escrever o código:
void write(std::string const& message)
{
// ...
}
Para sua surpresa, já existe uma outra função com exatamente a mesma assinatura, e você recebe o seguinte erro de
compilação: error: redefinition of 'void write(string)'
. De fato, existe um problema de ambiguidade: Ambas as funções
foram criadas para o mesmo propósito: escrever uma mensagem em um display. Porém, o display em questão é diferente
dependendo do contexto. Existem várias maneiras de resolver tal problema. Uma possibilidade é dividir as implementações
em namespaces
diferentes.
Um namespace
é uma estrutura que pode conter classes, funções e variáveis. Eles não servem apenas para desambiguar
uma função ou classe, mas também para organizar o projeto. Eles são estruturas opcionais, e não é raro encontrar
bibliotecas e aplicativos escritos em C++ que são implementados sem o uso de namespaces
.
Para resolver o problema comentado, poderia-se escrever o código anterior da seguinte forma:
namespace main_display {
void write(std::string const& message)
{
// ... Implementação do display principal
}
}
namespace secondary_display {
void write(std::string const& message)
{
// ... Implementação do display secundário
}
}
Para usar uma ou outra implementação, é necessário explicitar o namespace
ao chamar a função, da seguinte forma:
main_display::write("...exemplo...");
. Um código de exemplo é mostrado abaixo:
int main()
{
main_display::write("Mensagem no display principal");
secondary_display::write("Mensagem no display secundário");
return 0;
}
O namespace
mais comum nos programas C++ é o std
(namespace relacionado à biblioteca padrão). Inclusive, ele
apareceu já nos primeiros capítulos desse livro, para utilizar a função cout
:
#include <iostream>
int main()
{
std::cout << "Olá mundo!" << std::endl;
return 0;
}
No caso de você utilizar muitas funções e estruturas de dentro de um mesmo namespace
, é possível utilizar using
para
evitar a repetição do prefixo do namespace em questão, como no exemplo abaixo. Note, porém, que o uso de using
no
escopo global é desencorajado em alguns casos, pois pode afetar parcelas de código indesejadamente. Esse ponto será
discutido novamente em capítulos posteriores desse livro.
#include <iostream>
// Sugere-se evitar `using` global
// using namespace std;
int main()
{
// `using` dentro do escopo de alguma função é preferível
using namespace std;
cout << "Ol mundo!" << endl;
return 0;
}