两个"using"会碰撞吗?

Can two "using" collide?

本文关键字:碰撞 using 两个      更新时间:2023-10-16

所以我必须使用Boost库的一些成员和一些来自std命名空间。现在,我已经声明了using boost::asio::ip::tcp;,并使用std::和例如tcp::iostream server()调用适当的成员。有什么理由我不应该添加另一个using,即using namespace std;,然后调用所有没有std::前缀的std的东西?这两个会发生碰撞或导致故障吗?

using指令从std命名空间中导入名称通常被认为是一种不好的做法(特别是在命名空间作用域和头文件中),因为它很容易导致名称冲突,请考虑以下程序:

namespace A { void foo() { } }
namespace B { void foo() { } }
int main()
{
    using namespace A;
    using namespace B;
    foo();
}

编译器如何解析对foo()的调用?嗯,不会的。它是有歧义的,因为A::foo()B:foo()现在都可以被称为不限定的foo()

如果在std命名空间和全局命名空间中(或在任何其他有using指令的命名空间中)有相同名称的实体,则可能出现由于名称冲突而产生的歧义。

在您的特定情况下,using指令,如:

using namespace std;

不太可能与using 声明引入的名称tcp冲突(注意,using声明只导入一个特定的名称,因此更可取)。

然而,它仍然被认为是糟糕的编程风格,你不应该这样做,不管你是否有一些其他的using指令或using声明已经到位。

是的,他们可以。在这种情况下,编译器无法解析正确的名称空间。解决方案是使用前缀(例如std::)。

您还可以将using namespace关键字放在函数或其他块中,这样命名空间就不会在函数或其他块之外使用:

void foo()
{
    using namespace ns;
} // ns won't be used after this

此外,名称空间的使用可以限制为头:

namespace ns
{
    #include "ns.h"
}

但是,不建议将名称空间限制为标题,因为在许多情况下这会导致问题。

其他答案很好地解释了当您有两个或多个using namespace 指令时如何解决歧义,但值得指出的是,如果您有using 声明从名称空间中拉入两个或多个特定名称,情况就不同了,如:

namespace A { void foo() { } }
namespace B { void foo() { } }
int main()
{
    using A::foo;
    using B::foo;
    return 0;
}
上面的

总是一个编译错误,即使没有使用foo。这是因为using 声明,顾名思义,实际上声明在其封闭范围内的名称是其他名称空间中的名称的别名。这与using namespace 指令相反,仅仅使名称在其封闭范围内可用,而不实际声明任何新名称。

如果你真的想,可以像这样解析上面的代码:

using fooa = A::foo;
using foob = B::foo;

但是using 声明通常应该避免,因为它们有一些其他的语义意外,这些意外会以意想不到的、微妙的、有时是无法察觉的方式伤害你。例外是using,它是派生类中的基类成员,这通常是可以的,尽管通常不是必需的。