缩短嵌套的命名空间名称

时间:2009-11-02 14:08:43

标签: c++ namespaces

如果使用嵌套命名空间,则头文件中的声明可能会变得很长且不可读。

//header1
namespace test { namespace test1 {
class Test {};
} } //namespace

在节目的标题2中:

#include "header1"

namespace test2 {

class Test1 {
  void test(test::test1::Test &test) {}
  void test1(test::test1::Test &test) {}
  void test2(test::test1::Test &test1, test::test1::Test &test2) {}
};

}

是否有可能缩短header2中的名称?

5 个答案:

答案 0 :(得分:6)

这是我最喜欢的技术:

#include "header1"

namespace test2 {

class Test1 {
 private:
  typedef ::test::test1::Test MeaningfulName;

  void test(MeaningfulName &test) {}
  void test1(MeaningfulName &test) {}
  void test2(MeaningfulName &test1, MeaningfulName &test2) {}
};

}

我将typedef别名设为私有,但我将它们放在类声明的开头。它们对程序的其余部分是私有的并不重要,因为没有人会使用别名,他们将使用实际的类型名称或他们自己的名称别名。

我也非常喜欢使用锚定的命名空间名称以避免以后的意外。我的规则是我总是使用锚定名称,除非名称空间是我控制的名称和/或是当前项目或包的一部分或其他。然后我将使用最短的相对名称。如果该相对名称将从根命名空间开始,我仍然经常使用锚定名称。

主要问题是有向图<:,一旦你更频繁地开始使用锚定名称,它会在模板声明中出现很多。你必须放入一个空间来避免它,特别是因为有向图处理在很早的阶段发生,并且可以给你一些非常奇怪的错误信息。

答案 1 :(得分:4)

您可以使用别名命名空间,如下所示:

namespace tt=test::test1;

答案 2 :(得分:1)

有些方法可以通过使用别名或using关键字来缩短名称,但它们几乎总是一个坏主意。命名空间存在是有原因的,原因是保持事物分离。只要将using关键字放在头文件中就可以打破这种分离,并且完全不使用命名空间。如果你在using namespace test1中实现内容,你可以在你的cpp文件中随意test1,但我建议你不要在你的头文件中这样做,因为它与把它放在包含该标头的每个cpp文件的顶部。

您必须记住的是,在标头中声明某些内容与在包含该标头的每个cpp文件中声明它相同。值得一提的是,“如果你经常在test2中使用test1,为什么它们会有不同的命名空间?”

答案 3 :(得分:0)

在文件header2.h中

using namespace test::test1;

答案 4 :(得分:0)

虽然这是一个老问题,但我觉得我应该提出解决这个问题的方法,特别是因为它是谷歌中针对该主题弹出的第一批结果之一,可能会帮助其他人。

这个方法绝对不是最安全的,因为它涉及使用预处理程序指令,但我喜欢使用#define和#undef缩短标题中的命名空间。

以下是一个例子:

#include "header1"

#define shortNS test::test1
namespace test2 {
    class Test1 {
        void test(shortNS::test &test) {}
        void test1(shortNS::test &test) {}
        void test2(shortNS::test &test1, shortNS::test &test2) {}
    };
}
#undef shortNS

基本上它的工作原理是创建一个名为“shortNS”的定义,预处理器盲目地替换为“test :: test1”,定义之后它就会发生。当然,定义一个宏的问题在于它不受任何形式或形式的范围限制,这可能造成严重破坏,并且已知会导致任何毫无戒心的程序员在尝试调试时失去理智。

所以为了防止一旦我们完成定义,我们#undef shortNS告诉预处理器停止用“test :: test1”替换“shortNS”。这允许我们在某种程度上模拟范围。在上面的示例中,我将shortNS限制为文件的“范围”。

这是我头脑中的优缺点列表。

优点:

  • 允许您手动限制范围。 (只需半个功能吗?当然。)
  • 对包括该文件在内的任何人透明。
  • 没有像“namespace a = b :: c”
  • 这样的遗留名称空间
  • “using namespace”
  • 没有命名空间冲突
  • 不会将命名空间带入当前命名空间(如“使用命名空间”)

缺点:

  • 缩短名称空间定义中的任何错误都会出现在宏从不使用的任何地方。
  • 如果在#define #undef“block”中包含文件,则会在包含的文件中使用define,这可能会导致意外结果和/或令人头疼。
  • 如果你忘了#undef,它会/将会破坏你,你会疯了。
  • 这有点笨重。
  • 维护代码的人会讨厌你。

长话短说,如果你对宏感到满意并且不介意在出错时试着调试它,请继续。预处理器是一个非常非常强大的东西,但它就像在你的脚上贴一点C4并捣碎键盘来设置计时器 - 你不知道什么时候会把你的腿吹走。