所以我必须使用 Boost 库的一些成员和 std 命名空间中的一些成员。现在,我已经using boost::asio::ip::tcp;
声明并正在调用适当的成员,std::
例如tcp::iostream server()
. 有什么理由我不应该添加另一个using
,即using namespace std;
然后调用所有std
没有std::
前缀的东西?这两者会以某种方式发生碰撞或导致故障吗?
3 回答
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;
不太可能与您的声明tcp
引入的名称发生冲突(请注意,声明仅导入一个特定名称,因此更可取)。using
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
declarations,顾名思义,实际上在其封闭范围内声明了一个名称,以作为其他名称空间中名称的别名。这与指令相反,using namespace
指令仅使名称在其封闭范围内可用,而不实际声明任何新名称。
如果你真的想,可以像这样解决上面的代码:
using fooa = A::foo;
using foob = B::foo;
但是无论如何通常都应该避免using
声明,因为它们还有一些其他语义上的惊喜,它们可能会以意想不到的、微妙的,有时甚至是无法察觉的方式咬你。例外是using
派生类中的基类成员,这通常是可以的,但通常不是必需的。