我发现我认为在c ++中使用命名空间的“最佳实践”会损害我的代码的可读性,并让我质疑如何很好地使用它们。
我的程序由几个不同的模块组成,这些模块主要构建在“主”应用程序使用的库中。每个库都使用它自己的命名空间,它们的命名空间都在项目命名空间的“内部”,以帮助预测与第三方代码的名称冲突。所以我最终得到了类名,例如“myproject :: logging :: Logger”和“myproject :: reporting :: ReportType”(作为例子)。
到目前为止一切顺利。在我的.cpp文件中我没有问题。我在顶部使用“使用myproject :: logging”,并且可以干净地引用我的Logging类。如果我的两个命名空间之间发生冲突,我可以明确地说出我想要的那个。这很有效。
头文件虽然不同。将使用语句放入头文件中被认为是不好的做法,因为它们会影响可能不期望它们的不相关代码。所以我总是完全限定.hpp文件中的所有名称。到目前为止,这有点难看但是可以管理,所以我忍受了。但现在我在我的库中使用模板代码越来越多,这意味着我的.hpp文件中有更多实际代码。由于类型名称的长度,必须完全限定每个名称使得代码几乎不可读。
我开始觉得命名空间的好处和使用它们的最佳实践开始被我不得不写的代码的不可读性所抵消。我开始怀疑我是否会更好地放弃使用命名空间来获得更易读的代码的好处,并在它们出现时修复任何名称冲突。
另一种方法是使用短的单层命名空间,而不是“myproject :: logging :: Logger”,我只会使用“log :: Logger”,它可以帮助很多,但会使命名空间冲突的可能性更高,并且命名空间也传达了较少的有用信息。
正如我所说,这只会影响.hpp文件中的代码,因为我很高兴在我的实现文件中使用“using namespace”来使这个可管理,但 成为一个问题当我在.hpp文件中查看我的模板化代码并认为“eww ....”这不可能是好的:P
有人有任何实用的建议吗?
答案 0 :(得分:20)
这就是我的所作所为。
在<mylibrary.h>
:
namespace myproject {
namespace mylibrary
{
namespace impl
{
using namespace otherlibrary;
using namespace boost;
using namespace std;
using namespace whatever::floats::your::boat;
class myclass;
class myotherclass;
};
using impl::myclass;
using impl::myotherclass;
};
};
来源:
#include <mylibrary.h>
using namespace myproject::mylibrary; //clean!
答案 1 :(得分:18)
我之前一直处于这种状况。通常情况下,标题中的许多模板函数/类实际上都是“实现”,尽管由于C ++中模板的性质,您不得不将它们放在头文件中。因此,我只是将所有内容放在一些“详细信息”或“实现”命名空间中,我可以轻松地使用“使用命名空间”。最后,我“贬低”人们应该使用的东西到相应的地方。像这样:
namespace myproject { namespace somemodule {
namespace _implementation {
using namespace myproject::othermodule;
using namespace myproject::yetanothermodule;
template <...>
class some_internal_metafunction{
...
};
template <...>
class stuff_people_should_use_outside {
...
};
} // namespace implementation
using stuff_people_should_use_outside ;
}} // namespace myproject::somemodule
但是,这种方法可能会扩大编译器报告中的名称。
或者,您可以放弃模块名称空间。但对于一个非常大的项目来说,这可能不是一个好主意。
答案 2 :(得分:5)
个人?我摆脱了“myproject”部分。您的库使用与另一个完全相同的命名空间名称的可能性是多少,而有一个与另一个名称相同的符号?
另外,我建议您更希望在标题中使用名称空间的名称。
答案 3 :(得分:2)
我的经验是,由于您在原始帖子中提到的原因,为所有代码创建一个命名空间会更方便。此命名空间可防止您的标识符与第三方库中的标识符冲突。你的命名空间是你的主宰,很容易保持名称冲突免费。
答案 4 :(得分:0)
如果你的项目不是很大(我的意思是,非常巨大),那么只使用myproject应该足够了。如果您真的想将项目划分为多个部分,则可以使用更通用的命名空间。例如,如果我正在构建游戏引擎,我会选择MyEngine :: Core,MyEngine :: Renderer,MyEngine :: Input,MyEngine :: Sound等命名空间。
答案 5 :(得分:0)
我使用以下方法摆脱头文件中大量的std::
:
// mylibrary.h
namespace myproject {
namespace mylibrary {
namespace impl {
using namespace std;
namespace stripped_std {
// Here goes normal structure of your program:
// classes, nested namespaces etc.
class myclass;
namespace my_inner_namespace {
...
}
} // namespace stripped_std
} // namespace impl
using namespace impl::stripped_std;
} // namespace mylibrary
} namespace myproject
// Usage in .cpp file
#include <mylibrary.h>
using namespace myproject::mylibrary;
它类似于n.m.的建议,但有一个修改:
还有一个辅助命名空间stripped_std
。
总体效果是,行using namespace myproject::mylibrary;
允许您引用内部名称空间结构,但同时也不会将namespace std
带入库用户的作用域。
可惜以下语法
using namespace std {
...
}
在撰写本文时,在C ++中无效。