如果使用嵌套命名空间,则头文件中的声明可能会变得很长且不可读。
//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中的名称?
答案 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限制为文件的“范围”。
这是我头脑中的优缺点列表。
优点:
缺点:
长话短说,如果你对宏感到满意并且不介意在出错时试着调试它,请继续。预处理器是一个非常非常强大的东西,但它就像在你的脚上贴一点C4并捣碎键盘来设置计时器 - 你不知道什么时候会把你的腿吹走。