- 正确包含头文件(或前向声明我想要使用的类)
- 按名称使用这些类
这两个参数不是已经暗示了命名空间所传达的相同信息吗?现在使用命名空间会引入第三个参数-完全限定名称。如果库的实现发生了变化,现在有三个潜在的事情需要改变。这难道不是根据定义增加了库代码和我的代码之间耦合度吗?
例如,看看Xerces-C:它在名称空间中定义了一个纯虚接口称为Parser。我可以通过包括适当的头文件并使用using namespace XERCES_CPP_NAMESPACE或prefacing declarations / definitions with XERCES_CPP_NAMESPACE :: 来在我的代码中使用Parser接口。
随着代码的演变,也许有必要放弃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
是否更有优势?