C++中头文件中有更好的表达嵌套命名空间的方法吗?

130

我从C++转换到Java和C#,认为这些语言中命名空间/包的使用更好(结构化程度更高)。然后我回到了C++,试图以相同的方式使用命名空间,但在头文件中所需的语法令人不堪入目。

namespace MyCompany
{
    namespace MyModule
    {
        namespace MyModulePart //e.g. Input
        {
            namespace MySubModulePart
            {
                namespace ...
                {
                    public class MyClass    

以下内容对我来说也很奇怪(为了避免深度缩进):

namespace MyCompany
{
namespace MyModule
{
namespace MyModulePart //e.g. Input
{
namespace MySubModulePart
{
namespace ...
{
     public class MyClass
     {

有没有更简洁的方式来表达上述内容?我是否缺少像这样的东西

namespace MyCompany::MyModule::MyModulePart::...
{
   public class MyClass

更新

好的,有人说Java/C#和C++中的命名空间概念是不同的。真的吗?我认为(动态)类加载不是命名空间的唯一目的(这是一个非常专业的理性观点)。为什么不能用它来提高可读性和结构化程度,比如考虑 "IntelliSense"。

目前,命名空间与其中的内容之间没有逻辑 / 粘合剂。Java 和 C# 做得更好... 为什么要包含 <iostream> 并使用命名空间 std? 如果你说逻辑应该依赖于头文件的包含,那为什么 #include 不使用类似于 "IntelliSense" 友好的语法,比如 #include <std::io::stream> 或者 <std/io/stream>?我认为缺少默认库的结构化是 C++ 相对于 Java/C# 的一个弱点。

如果避免冲突的独特性是一个点(这也是 C# 和 Java 的一个点),那么使用项目名称或公司名称作为命名空间是一个好主意,你不觉得吗?

一方面,有人说 C++ 是最灵活的...但每个人都说 "不要这样做"? 对我来说,C++ 可以做很多事情,但在许多情况下,即使是最简单的事情,它的语法也很可怕,相比之下 C# 更好。

更新2

大多数用户说创建超过两个级别的深度嵌套是无意义的。那么 Win8 开发中的 Windows::UI::Xaml 和 Windows::UI::Xaml::Controls::Primitives 命名空间怎么办?我认为微软使用命名空间是有道理的,而且确实比只有2个级别更深。 我认为更大的库 / 项目需要更深的嵌套(我讨厌类名像 ExtraLongClassNameBecauseEveryThingIsInTheSameNameSpace...然后你也可以把一切都放到全局命名空间中。)

更新3-结论

大多数人说 "不要这样做",但是...甚至 boost 的嵌套层次也比一个或两个层次深。是的,它是一个库,但是:如果你想要可重用的代码-把自己的代码当作你给别人的库。我还使用更深的命名空间嵌套来进行发现。


3
namespace е…ій”®еӯ—зҡ„дҪҝз”ЁжҳҜеҗҰжңүж»Ҙз”Ёпјҹ - Nawaz
4
命名空间和C#/Java模块系统的目的不同,因此您不应尝试以相同的方式使用它们。没有更简单的语法,因为为本不应该做的事情提供语法来简化操作是没有意义的。 - PlasmaHH
3
@PlasmaHH 提到了针对/在包含头文件后的Intellisense和其他辅助工具。一个公司内的大型项目可能需要多个嵌套(例如vw::golflib::io),以清晰地说明命名空间包含哪些“范围”。当然,您可以只使用vw::,但是如果命名空间旨在用于避免冲突,为什么声明起来如此麻烦?这导致没有人使用它或者只使用深度为一的命名空间(如经常建议的那样)。 - Beachwalker
@Stegi:智能感知是一个无意义的争论,如果它无法处理通过头文件名称导入的问题,那么你应该修复它,而不是改变语言使其更好地工作。我的自动完成功能完全正常,没有无休止的嵌套命名空间。嵌套命名空间会打开指数级的命名空间。如果您需要将命名空间嵌套5层深,因为您有32个具有相同名称的类,则您正在做一些非常错误的事情。命名空间不能替代文档中的分组。 - PlasmaHH
1
谢谢您提出这个问题,我也觉得C++确实缺少这样的功能! - alexpanter
显示剩余3条评论
11个回答

0
你可以使用这个语法:
namespace MyCompany {
  namespace MyModule {
    namespace MyModulePart //e.g. Input {
      namespace MySubModulePart {
        namespace ... {
          class MyClass;
        }
      }
    }
  }
}

// Here is where the magic happens
class MyCompany::MyModule::MyModulePart::MySubModulePart::MyYouGetTheIdeaModule::MyClass {
    ...
};

请注意,即使在C++98中,此语法也是有效的,并且与C++17中现在可用的嵌套命名空间定义几乎相似。

祝你愉快!

来源:


这是问题中提到的语法,而现在,根据被接受的答案所述,使用C++17是一种有效的替代方法。抱歉,因未阅读问题和答案而被点踩。 - Beachwalker
@Beachwalker,我们不要陷入语法的纠结中。上面的命名空间声明也可以与被接受的答案相同。我想通过这个答案强调的主要点是,OP所说他错过的东西,以及我在那个命名空间混乱之下所做的事情。据我所见,每个人似乎都集中精力在命名空间内声明所有内容,而我的答案将您从嵌套的混乱中解放出来,我相信如果有人在4年前首次提出这个问题时提到了这个语法,OP一定会很感激的。 - smac89

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接