C++中的命名空间和打包

And*_*rew 5 c++ architecture packaging namespaces inversion-of-control

在打包代码中使用命名空间的最佳/最干净方法是什么?

例如在像boost这样的库中似乎有非常有组织的命名空间管理,使用了一些允许消除名称歧义的技术.然而,重要的是,人们不会看到很多代码

typedef namespace1::namespace2::sth_else::a_class<namespace3::namespace4::b_class> type;
Run Code Online (Sandbox Code Playgroud)

通常,没有太多的跨名称空间,这表明良好的体系结构,但也有良好的命名空间管理.问题是:什么是良好的命名空间管理?

假设我们有这样的文件结构:

component1/...  (depends on reusable_if)
component2/...  (depends directly on reusable_if and on component 1)
reusable/
reusable/some_part/
reusable/some_part/...
reusable/some_other_part/
reusable/some_other_part/...
reusable/SthThatUsesBothReusableParts.h   (implements reusable_if/ISth.h)
reusable/SthThatUsesBothReusableParts.cpp (implements reusable_if/ISth.h)
reusable_if/
reusable_if/ISth.h   (pure abstract class)
reusable_if/ISthElse.h (pure abstract class)
main.cpp (e.g. instantiates SthThatUsesBothReusableParts and passes to component1/2)
Run Code Online (Sandbox Code Playgroud)

存在reusable_if /文件夹的原因是因为component1和component2都想重用相同的接口(因此它们都没有'独占'接口).此外,假设项目确实非常大,并且需要为每个文件夹中的类提供适当的名称空间.

如何在这样的项目中应用名称空间?假设我在可重用/在命名空间中声明所有类::reusable.我应该将reusable_if中的接口放入命名空间::reusable还是放入::reusable_if?或者也许没有,因为它被component1和component2使用?

component1和component2中的命名空间怎么样?有什么要记住的吗?关键字using怎么样?假设我决定添加此::reusable_if命名空间.我可以把using reusable_if成头文件中COMPONENT1和COMPONENT2,只要using ...放在里面的命名空间::component1::component2

我愿意接受任何建议,也不一定与上述例子有关.

Dev*_*lar 6

个人意见免责声明。您的问题基本上要求主观答案,并且可能会因此而关闭,但我会试一试。


命名空间主要用于避免标识符冲突。有“你的”命名空间 ( mylib::),以及其他所有人的命名空间 ( std::, boost::, icu::, ...),这就是命名空间应该被采用的范围。

将您的项目(如“您团队的项目”)细分为子命名空间几乎没有什么好处,除非您遇到标识符冲突的问题——在这种情况下,您应该重新考虑调用类XY. ;-)

巨大的库中,情况有点不同,比如 Boost。它们实际上由许多不同的项目组成,由不同的团队维护,因此如果将特定于项目的标识符全部混为一谈,就会存在项目特定标识符相互冲突的问题boost::(并且冲突可能不会出现在临时测试中)。

如果你停止寻找boost::filesystem一个“子命名空间”,而是看boost::作为一个“身份包装”的个别项目filesystem::thread::program_options::和诸如此类的东西,让他们看起来更“助推十岁上下”,画面变得更清晰。


Tem*_*Rex 5

这是我在我的项目中使用的。我的主要规则是每个目录都是一个命名空间,每个文件都是一个类,很少有例外(有时我将辅助函数分组在命名空间的子目录中detail,但没有另一个嵌套命名空间)。

  1. 将整个项目保存在以您的项目命名的单个顶级命名空间中。

  2. 将每个实用程序组件保留在顶级命名空间内,但位于单独的目录中。这是我唯一一次不让命名空间与目录树重叠。

  3. 将项目中每个可独立发布的组件保存在以组件命名的嵌套命名空间内。为了方便起见,请提供一个以您的组件命名的标头,并在与您的命名空间对应的目录中或直接在项目的顶级目录中包含整个组件接口。

  4. 将每个组件的实现保留在嵌套命名空间内detail。与类相反,命名空间没有对private成员的语言支持,但 Boost 中的约定是命名空间detail不应直接由用户代码调用。

不需要比project::component::detail::function()或进一步嵌套。project:::component::class.member()如果您提供有利于 ADL 的完整接口,则可以在项目中重用组件函数作为类型function(x)变量,而不必担心名称冲突。xproject::component::class

请注意,用鲍勃叔叔的话来说:“重用的单位就是发布的单位”。每个组件应该提供一堆连贯且相互依赖的类和函数。特别是,它应该为该组件提供完整的接口。C++ 语言将通过参数相关查找(ADL) 支持这一点。请参阅Herb Sutter 撰写的旧专栏“命名空间和接口原理”。

和 的存在以及两者reuse_if的存在可能会产生代码味道,除非您在注释中提到的注意事项实际上适用。组件应该是发布的单位。如果您可以独立地重用一段代码,请将其作为一个单独的组件。如果代码依赖于另一部分,请将其与其他代码一起发布。有关这些依赖关系,请参阅 Sutter 的专栏。componentreusable