Я понимаю, что библиотека C ++ должна использовать пространство имен, чтобы избежать конфликтов имен, но так как мне уже нужно:
#include
правильный заголовок (или форвард объявите классы, которые я намерен использовать)
- Используйте эти классы по имени
Не эти два параметра выводят ту же информацию, передаваемую пространством имен. Использование пространства имен теперь вводит третий параметр - полное имя. Если реализация библиотеки изменится, теперь есть три потенциальных вещей, которые мне нужно изменить. Разве это не по определению увеличение связи между библиотечным кодом и моим кодом?
Например, посмотрите на Xerces-C: он определяет чисто виртуальный интерфейс с именем Parser
в пространстве имен XERCES_CPP_NAMESPACE
. Я могу использовать интерфейс Parser
в своем коде, включив соответствующий заголовочный файл и затем либо импортировав пространство имен using namespace XERCES_CPP_NAMESPACE
, либо предварительно добавив объявления / определения с помощью XERCES_CPP_NAMESPACE::
.
По мере развития кода, возможно, придется отказаться от Xerces в пользу другого парсера. Я частично «защищен» от изменений в реализации библиотеки чисто виртуальным интерфейсом (тем более, если я использую фабрику для создания моего анализатора), но как только я переключаюсь с Xerces на что-то другое, мне нужно прочесать мой код и изменить весь мой код using namespace XERCES_CPP_NAMESPACE
и XERCES_CPP_NAMESPACE::Parser
.
Я столкнулся с этим недавно, когда я реорганизовал существующий проект C ++, чтобы разделить некоторые существующие полезные функции в библиотеку:
foo.h
class Useful; // Forward Declaration
class Foo
{
public:
Foo(const Useful& u);
...snip...
}
foo.cpp
#include "foo.h"
#include "useful.h" // Useful Library
Foo::Foo(const Useful& u)
{
... snip ...
}
В значительной степени из-за невежества (и частично из-за лени) в то время вся функциональность useful.lib
была помещена в глобальное пространство имен.
По мере роста содержания useful.lib
(и все больше клиентов начали использовать эту функциональность) было решено переместить весь код из useful.lib
в его собственное пространство имен с именем "useful"
.
Клиентские .cpp
файлы было легко исправить, просто добавьте using namespace useful
;
foo.cpp
#include "foo.h"
#include "useful.h" // Useful Library
using namespace useful;
Foo::Foo(const Useful& u)
{
... snip ...
}
Но файлы .h
были действительно трудоемкими. Вместо того, чтобы загрязнять глобальное пространство имен, помещая using namespace useful;
в заголовочные файлы, я обернул существующие предварительные объявления в пространство имен:
foo.h
namespace useful {
class Useful; // Forward Declaration
}
class Foo
{
public:
Foo(const useful::Useful& u);
...snip...
}
Были десятки ( и десятки ) файлов, и это стало большой болью! Это не должно было быть так сложно. Очевидно, что я сделал что-то не так с дизайном и / или реализацией.
Хотя я знаю, что код библиотеки должен находиться в своем собственном пространстве имен, было бы выгодно, чтобы код библиотеки оставался в глобальном пространстве имен и вместо этого попытался управлять #includes
?