Bea*_*ker 85 c++ syntax namespaces
我从C++切换到Java和C#,并认为命名空间/包的使用在那里(结构良好)更好.然后我回到C++并试图以相同的方式使用命名空间,但在头文件中所需的语法是可怕的.
namespace MyCompany
{
namespace MyModule
{
namespace MyModulePart //e.g. Input
{
namespace MySubModulePart
{
namespace ...
{
public class MyClass
Run Code Online (Sandbox Code Playgroud)
以下内容对我来说也很奇怪(避免深度缩进):
namespace MyCompany
{
namespace MyModule
{
namespace MyModulePart //e.g. Input
{
namespace MySubModulePart
{
namespace ...
{
public class MyClass
{
Run Code Online (Sandbox Code Playgroud)
是否有更短的方式来表达上述事情?我错过了类似的东西
namespace MyCompany::MyModule::MyModulePart::...
{
public class MyClass
Run Code Online (Sandbox Code Playgroud)
更新
好吧,有人说Java/C#和C++中的使用概念是不同的.真?我认为(动态)类加载不是命名空间的唯一目的(这是一个非常技术性的推理视角).为什么我不应该将它用于可读性和结构化,例如想到"IntelliSense".
目前,命名空间与您可以在其中找到的内容之间没有逻辑/粘合剂.Java和C#做得更好......为什么要包含<iostream>和拥有命名空间std?好吧,如果你说的逻辑应该依靠头部以包括,为什么#包括不使用的"智能感知"友好的语法像#include <std::io::stream>或<std/io/stream>?我认为与Java/C#相比,缺省库中缺少的结构化是C++的一个弱点.
如果狂热冲突的唯一性是一个Point(这也是C#和Java的一个点),一个好主意是使用项目名称或公司名称作为命名空间,你不这么认为吗?
一方面它说C++是最灵活的...但每个人都说"不要这样做"?在我看来,C++可以做很多事情,但是在很多情况下,与C#相比,即使是最简单的事情也会有一种可怕的语法.
更新2
大多数用户认为创建比两个级别更深的嵌套是无稽之谈.好的,那么Win8开发中的Windows :: UI :: Xaml和Windows :: UI :: Xaml :: Controls :: Primitives名称空间呢?我认为微软对名称空间的使用是有道理的,它确实比仅仅2级更深.我认为更大的库/项目需要更深层次的嵌套(我讨厌像ExtraLongClassNameBecauseEveryThingIsInTheSameNameSpace这样的类名...那么你也可以将所有东西放到全局命名空间中.)
更新3 - 结论
大多数人说"不要这样做",但是......甚至提升都有一个更深的嵌套,然后是一个或两个级别.是的,它是一个库,但是:如果你想要可重复使用的代码 - 将你自己的代码视为一个库你可以给别人.我还使用更深层次的嵌套来使用命名空间进行发现.
W1M*_*M0R 115
C++ 17可能会简化嵌套的命名空间定义:
namespace A::B::C {
}
Run Code Online (Sandbox Code Playgroud)
相当于
namespace A { namespace B { namespace C {
} } }
Run Code Online (Sandbox Code Playgroud)
有关cppreference的命名空间页面,请参阅(8):http:
//en.cppreference.com/w/cpp/language/namespace
Kur*_*son 27
为了避免真正的深度缩进,我通常这样做:
namespace A { namespace B { namespace C
{
class X
{
// ...
};
}}}
Run Code Online (Sandbox Code Playgroud)
Pot*_*ter 13
C++命名空间用于分组接口,而不是划分组件或表达政治分裂.
该标准禁止使用类似Java的命名空间.例如,命名空间别名提供了一种轻松使用深层嵌套或长命名空间名称的方法.
namespace a {
namespace b {
namespace c {}
}
}
namespace nsc = a::b::c;
Run Code Online (Sandbox Code Playgroud)
但是namespace nsc {}这将是一个错误,因为命名空间只能使用其原始名称空间名称来定义.基本上,标准使这样的库的用户容易,但实施者很难.这会阻止人们写这些东西,但如果他们这样做,就会减轻影响.
每个接口应该有一个命名空间,由一组相关的类和函数定义.内部或可选的子接口可能会进入嵌套的命名空间.但超过两个级别应该是一个非常严重的危险信号.
考虑使用::不需要运算符的下划线字符和标识符前缀.
Max*_*uxa 13
我完全支持peterchen的回答,但想要添加一些解决你问题另一部分的内容.
声明命名空间是C++中非常罕见的情况之一,我实际上喜欢使用#defines.
#define MY_COMPANY_BEGIN namespace MyCompany { // begin of the MyCompany namespace
#define MY_COMPANY_END } // end of the MyCompany namespace
#define MY_LIBRARY_BEGIN namespace MyLibrary { // begin of the MyLibrary namespace
#define MY_LIBRARY_END } // end of the MyLibrary namespace
Run Code Online (Sandbox Code Playgroud)
这也消除了命名空间右括号附近的注释需求(你是否曾向下滚动到一个大型源文件的底部,并尝试添加/删除/平衡缺少关于哪个括号关闭哪个范围的注释的大括号?不好玩).
MY_COMPANY_BEGIN
MY_LIBRARY_BEGIN
class X { };
class Y { };
MY_LIBRARY_END
MY_COMPANY_END
Run Code Online (Sandbox Code Playgroud)
如果你想将所有名称空间声明放在一行上,你也可以使用一些(非常难看的)预处理器魔法:
// helper macros for variadic macro overloading
#define VA_HELPER_EXPAND(_X) _X // workaround for Visual Studio
#define VA_COUNT_HELPER(_1, _2, _3, _4, _5, _6, _Count, ...) _Count
#define VA_COUNT(...) VA_HELPER_EXPAND(VA_COUNT_HELPER(__VA_ARGS__, 6, 5, 4, 3, 2, 1))
#define VA_SELECT_CAT(_Name, _Count, ...) VA_HELPER_EXPAND(_Name##_Count(__VA_ARGS__))
#define VA_SELECT_HELPER(_Name, _Count, ...) VA_SELECT_CAT(_Name, _Count, __VA_ARGS__)
#define VA_SELECT(_Name, ...) VA_SELECT_HELPER(_Name, VA_COUNT(__VA_ARGS__), __VA_ARGS__)
// overloads for NAMESPACE_BEGIN
#define NAMESPACE_BEGIN_HELPER1(_Ns1) namespace _Ns1 {
#define NAMESPACE_BEGIN_HELPER2(_Ns1, _Ns2) namespace _Ns1 { NAMESPACE_BEGIN_HELPER1(_Ns2)
#define NAMESPACE_BEGIN_HELPER3(_Ns1, _Ns2, _Ns3) namespace _Ns1 { NAMESPACE_BEGIN_HELPER2(_Ns2, _Ns3)
// overloads for NAMESPACE_END
#define NAMESPACE_END_HELPER1(_Ns1) }
#define NAMESPACE_END_HELPER2(_Ns1, _Ns2) } NAMESPACE_END_HELPER1(_Ns2)
#define NAMESPACE_END_HELPER3(_Ns1, _Ns2, _Ns3) } NAMESPACE_END_HELPER2(_Ns2, _Ns3)
// final macros
#define NAMESPACE_BEGIN(_Namespace, ...) VA_SELECT(NAMESPACE_BEGIN_HELPER, _Namespace, __VA_ARGS__)
#define NAMESPACE_END(_Namespace, ...) VA_SELECT(NAMESPACE_END_HELPER, _Namespace, __VA_ARGS__)
Run Code Online (Sandbox Code Playgroud)
现在你可以这样做:
NAMESPACE_BEGIN(Foo, Bar, Baz)
class X { };
NAMESPACE_END(Baz, Bar, Foo) // order doesn't matter, NAMESPACE_END(a, b, c) would work equally well
Foo::Bar::Baz::X x;
Run Code Online (Sandbox Code Playgroud)
对于嵌套深度超过三个级别,您必须将助手宏添加到所需的计数.
不,请不要那样做.
命名空间的目的主要是解决全局命名空间中的冲突.
次要目的是符号的局部缩写; 例如,复杂UpdateUI方法可以使用a using namespace WndUI来使用较短的符号.
我正在使用1.3MLoc项目,我们唯一的命名空间是:
#import和之间的头冲突
#include windows.h)ModuleDetailHereBeTygers仅限标题库中的命名空间)在这个项目中,类名等使用两个或三个字母的"区域"代码(例如CDBNode代替DB::CNode).如果您更喜欢后者,则可以使用第二级"公共"命名空间,但不能再使用.
特定于类的枚举等可以是这些类的成员(虽然我同意这并不总是好的,有时很难说你是否应该这样做)
很少需要一个"公司"命名空间,除非你遇到了以二进制形式分发的第三方库的大问题,不提供自己的命名空间,并且不能轻易地放入一个(例如二进制文件中)分配).不过,根据我的经验,强迫他们进入命名空间更容易.
[编辑]根据Stegi的后续问题:
好的,那么Win8开发中的Windows :: UI :: Xaml和Windows :: UI :: Xaml :: Controls :: Primitives名称空间呢?我认为微软对名称空间的使用是有道理的,它确实比仅仅2级更深
对不起,如果我不够清楚:两个级别不是硬限制,更多不是本质上不好.我只想指出,根据我的经验,即使是在大型代码库中,您也很少需要两个以上.更深或更浅的嵌套是一种权衡.
现在,微软的案例可以说是不同的.大概是一个更大的团队,所有代码都是库.
我假设微软在这里模仿.NET库的成功,其中命名空间有助于扩展库的可发现性.(.NET有大约18000种类型.)
我进一步假设命名空间中存在最佳(数量级)符号.比如说,1没有意义,100个声音正确,10000个显然是很多.
TL; DR:这是一个权衡,我们没有硬数字.玩安全,不要在任何方向过度."不要那样做"只来自"你有问题,我有问题,我没有理由你需要它."
这里引用了Lzz (Lazy C++) 文档:
Lzz 识别以下 C++ 结构:
命名空间定义
未命名的命名空间和所有封闭的声明都输出到源文件。此规则覆盖所有其他规则。
命名空间的名称可以被限定。
Run Code Online (Sandbox Code Playgroud)namespace A::B { typedef int I; }相当于:
Run Code Online (Sandbox Code Playgroud)namespace A { namespace B { typedef int I; } }
当然,依赖于这些工具的源代码的质量是有争议的......我会说这更像是一种好奇心,表明由 C++ 引起的语法疾病可以有多种形式(我也有我的......)