什么是命名空间别名?

192
在C++中,“命名空间别名”是什么?它如何使用?
5个回答

228

命名空间别名是一种方便的方式,通过不同的短名称来引用长命名空间名称。

作为一个例子,假设你想要使用Boost的uBLAS中的数字向量而不使用using namespace指令。每次都写完整的命名空间名称很麻烦:

boost::numeric::ublas::vector<double> v;

相反,你可以为boost::numeric::ublas定义一个别名 -- 假设我们想将其缩写为ublas:

namespace ublas = boost::numeric::ublas;


ublas::vector<double> v;

8
可能是为了解释被踩的原因,SO并不是也永远不会成为优秀C++教材的替代品。你提出的问题可以在这样的书中得到解答。而SO“自问自答”的功能不应该用于提供这些书的释义。 - anon
32
没关系,只是想解释一下我为什么这样做:从Joel在播客中的评论中我理解到,即使是“入门级”问题在SO上也是可以提出的,并且如果该内容在SO上还没有以易懂的形式表述过,那么提问并自己回答是可以被接受的。但显然,这是不被赞同的? - Martin B
2
回答自己的问题也有一定的礼仪,以避免引起不必要的烦恼;在这种情况下,很明显它从来就不是一个真正的问题。例如,http://stackoverflow.com/questions/494927/stack-overflow-etiquette-for-answering-your-own-question - Marc Gravell
6
@Martin B: 我不赞同这是一个入门级别的问题 - 实际上,过去有很多更明显的问题,现在已经得到了很多投票。尽管如此,人们可能觉得你只是试图为自己赢得声誉。解决这个问题的方法是将问题/答案中的一个或两个标记为“社区wiki”。就我个人而言,我会选择问题作为你的回答作为社区。如果问题有价值,那么你会获得投资回报。 - Richard Corden
9
我已经用C++编程数年了,我的教科书在海外(真的很远),而且我不记得命名空间别名的语法。由于这个问题,答案只是一个点击之遥。所以不管作者是否回答自己的问题,这都是一个好问题和一个好答案。谢谢 :) - WaterFox
显示剩余7条评论

8
简单来说,#define 命令不起作用。
namespace Mine { class MyClass { public: int i; }; }
namespace His = Mine;
namespace Yours { class Mine: public His::MyClass { void f() { i = 1; } }; }

可以成功编译。帮助你解决命名空间/类名冲突的问题。

namespace Nope { class Oops { public: int j; }; }
#define Hmm Nope
namespace Drat { class Nope: public Hmm::Oops { void f () { j = 1; } }; }

在最后一行,“Hmm:Oops”是一个编译错误。预处理器将其更改为Nope:: Oops,但是Nope已经是一个类名。

3
#define是什么?也许你的回答是针对之前版本的问题? - einpoklum

4

还要注意,命名空间别名和using指令在编译时而非运行时解析。具体来说,它们都是用于告诉编译器在哪里查找名称的工具,如果在当前作用域或其任何父作用域中找不到特定符号,就可以使用这些工具。例如,以下两个示例都无法编译:

namespace A {
    int foo;
    namespace AA {
        int bar;
    } // namespace AA
    namespace AB {
        int bar;
    } // namespace AB
} // namespace A
namespace B {
    int foo;
    namespace BA {
        int bar;
    } // namespace BA
    namespace BB {
        int bar;
    } // namespace BB
} // namespace B

bool nsChooser1, nsChooser2;
// ...

// This doesn't work.
namespace C = (nsChooser1 ? A : B);
C::foo = 3;

// Neither does this.
// (Nor would it be advisable even if it does work, as compound if-else blocks without braces are easy to inadvertently break.)
if (nsChooser1)
    if (nsChooser2)
        using namespace A::AA;
    else
        using namespace A::AB;
else
    if (nsChooser2)
        using namespace B::BA;
    else
        using namespace B::BB;

现在,一个好奇的头脑可能已经注意到constexpr变量也在编译时使用,并想知道它们是否可以与别名或指令一起使用。据我所知,它们不能,尽管我可能对此有所错误。如果您需要在不同命名空间中使用相同名称的变量,并动态选择它们之间的区别,则必须使用引用或指针。
// Using the above namespaces...
int& foo = (nsChooser1 ? A::foo : B::foo);

int* bar;
if (nsChooser1) {
    if (nsChooser2) {
        bar = &A::AA::bar;
    } else {
        bar = &A::AB::bar;
    }
} else {
    if (nsChooser2) {
        bar = &B::BA::bar;
    } else {
        bar = &B::BB::bar;
    }
}

以上内容的实用性可能有限,但它应该能达到目的。
(对我可能在上述内容中错过的任何打字错误表示歉意。)

4

更多相关内容请参见此链接

这篇文章主要介绍如何为一个很长的命名空间选择一个别名,例如:

namespace SHORT = NamespaceFirst::NameSpaceNested::Meow

然后,在以后的代码中,你可以使用typedef来简化操作:

typedef SHORT::mytype

而不是

typedef NamespaceFirst::NameSpaceNested::Meow::mytype

需要注意的是,这种语法只适用于命名空间,不能包含类或类型。


-1
命名空间用于防止名称冲突。
例如:
namespace foo {
    class bar {
        //define it
    };
}

namespace baz {
    class bar {
        // define it
    };
}

现在你有两个名为bar的类,由于命名空间而完全不同和独立。

你展示的 "using namespace" 是为了让你不必指定要使用命名空间中的类。例如,std::string 变成了 string。

我的资源:https://www.quora.com/What-is-namespace-in-C++-1


然而,在您的代码中使用“using namespace”并不被推荐。如果一个带有“using namespace”的文件被包含在应用程序的不同文件中,它可能会产生混淆。突然间,不同的文件也开始使用这个命名空间。那么开发人员可能就不知道函数是从哪个库中使用的了。(他以为是从std中使用的,但实际上是从其他命名空间中使用的) - Adam Kuzański

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