没有显式编写名称空间

时间:2015-08-18 13:50:37

标签: c++

在C ++实现文件中,我可以选择编写类似的内容:

name::space::ClassName::someFunction(int param) {
    // impl
}

而不是

namespace name {
    namespace space {
        ClassName::someFunction(int param) {
            // impl
        }
    }
}

我觉得非常方便,更具可读性。这可以以某种方式在头文件中使用吗?像这样:

class name::space::ClassName {
    // declarations
};

而不是

namespace name {
    namespace space {
        class ClassName {
            // declarations
        };
    }
}

如果这样的事情是可能的,那么在哪些条件下呢?我可以想象,需要 forward声明命名空间 forward声明命名空间中的类,如下所示:

namespace name {
    namespace space {
        class ClassName;
    }
}

才能使用它:

class name::space::ClassName {
    // declarations
};

在头文件中。

但不知怎的,我无法让它工作 1] 。它甚至可能吗?困扰我的是,使用嵌套命名空间我必须缩进2个选项卡,直到我能够实际声明我的类。我想在我的头文件中使用该空格,但我不想省略选项卡,因为这将违反"大括号中的所有内容都需要标记一次" -rule(I我不知道是否有真实的名字。如果有,请原谅我的无知,我不知道:S

1] 我遇到的问题与问题无关。这种方法确实有效,但它有缺点(见接受的答案)。

4 个答案:

答案 0 :(得分:6)

不,它不起作用。一个问题是

namespace name {
    namespace space {
        class ClassName {
            // declarations
        }
    }
}

你可以说它是两个名称空间和一个类。

然而,

class name::space::ClassName {
    // declarations
}

您无法判断space是名称空间还是包含嵌套ClassName的类。

所能做的是保存在标签上。可以写

namespace name { namespace space {
    class ClassName {
        // declarations
    }
}}

答案 1 :(得分:6)

如果您只是不希望命名空间括号包含您的类定义,那么您当然可以通过在其他地方使用类声明来定义命名空间来实现这一点。这样,你可以想出这样的东西:

#ifndef MYCLASS_H
#define MYCLASS_H

namespace ClassNamespace { class MyClass; };

class ClassNamespace::MyClass
{
public:
    MyClass();
    ~MyClass();
    void a();
private:

};

#endif // MYCLASS_H
标题的

和:

#include "MyClass.h"

#include <iostream>

using namespace std;

ClassNamespace::MyClass::MyClass()
{
}

ClassNamespace::MyClass::~MyClass()
{
}

void ClassNamespace::MyClass::a()
{
    cout << "hello";
}

实施。

如您所见,命名空间不包含类定义,只包含其声明。

作为最后一点,我个人不知道你为什么要这样做或认为它看起来更好看。我个人更喜欢看到命名空间封装了类定义以及函数定义。但也许我一直是个奇怪的人......

答案 2 :(得分:2)

你所寻找的东西不起作用。

一种解释是,所有C ++ classstruct类型都与它们自己的命名空间(与该类具有相同的名称)隐式关联。

所以,给定

class name::space::ClassName
{
// declarations
};

编译器无法确定namespace是否实际上是名称空间或类(充其量,它必须断定构造是不明确的)。因此,在被告知name是其中的一个类之前,需要明确告知编译器space是一个命名空间,nameClassName中的命名空间。 / p>

因此需要

namespace name
{
    namespace space
    {
        class ClassName;
    }
}

转发指定两个名称空间并在其中转发声明ClassName

答案 3 :(得分:1)

不,这是不可能的。 定义命名空间的唯一方法是将namespace关键字与花括号结合使用。

  

7.3.1命名空间定义[namespace.def]

     

1命名空间定义的语法是

  namespace-name:
      original-namespace-name
      namespace-alias
  original-namespace-name:
      identifier
  namespace-definition:
      named-namespace-definition
      unnamed-namespace-definition
  named-namespace-definition:
      original-namespace-definition
      extension-namespace-definition
  original-namespace-definition:
      inlineopt namespace identifier { namespace-body }
  extension-namespace-definition:
      inlineopt namespace original-namespace-name { namespace-body }
  unnamed-namespace-definition:
      inlineopt namespace { namespace-body }
  namespace-body:
      declaration-seqopt

您可以在命名空间之外定义命名空间的成员,尽管它必须在namespace(强调我的)中声明

  

7.3.1.2命名空间成员定义[namespace.memdef]

     

2命名命名空间的成员也可以通过显式限定在该命名空间外定义(3.4.3.2)   如果已定义的实体已在命名空间中声明,则定义名称   并且该定义出现在包含声明的命名空间中的声明点之后   命名空间。

写作时

namespace name {
    namespace space {
        class ClassName;
    }
}

您没有向class ClassName声明namespace space,您只是提供转发声明