class C {
using namespace std; // error
};
namespace N {
using namespace std; // ok
}
int main () {
using namespace std; // ok
}
我想了解背后的动机。
class C {
using namespace std; // error
};
namespace N {
using namespace std; // ok
}
int main () {
using namespace std; // ok
}
我想了解背后的动机。
namespace Hello
{
typedef int World;
}
class Blah
{
using namespace Hello;
public:
World DoSomething();
}
//Should this be just World or Hello::World ?
World Blah::DoSomething()
{
//Is the using namespace valid in here?
}
由于没有明显的方法可以做到这一点,标准只是说你不能这样做。
现在,当我们谈论命名空间作用域时,这个问题就不那么令人困惑了:
namespace Hello
{
typedef int World;
}
namespace Other
{
using namespace Hello;
World DoSomething();
}
//We are outside of any namespace, so we have to fully qualify everything. Therefore either of these are correct:
//Hello was imported into Other, so everything that was in Hello is also in Other. Therefore this is okay:
Other::World Other::DoSomething()
{
//We're outside of a namespace; obviously the using namespace doesn't apply here.
//EDIT: Apparently I was wrong about that... see comments.
}
//The original type was Hello::World, so this is okay too.
Hello::World Other::DoSomething()
{
//Ditto
}
namespace Other
{
//namespace Hello has been imported into Other, and we are inside Other, so therefore we never need to qualify anything from Hello.
//Therefore this is unambiguiously right
World DoSomething()
{
//We're inside the namespace, obviously the using namespace does apply here.
}
}
namespace Hello;
(和在其中声明 extern
函数)。 - iammilindHello::World Blah::DoSomething()
或者 Blah::World Blah::DoSomething()
(如果允许的话)。在语言中,成员函数定义的返回类型不被视为类的作用域,因此必须进行限定。考虑使用在类作用域下替换 using
为 typedef Hello::World World;
的有效示例。所以这里不应该有任何意外情况。 - David Rodríguez - dribeas为什么C++标准会禁止呢?我不知道,请询问批准该语言标准的ISO委员会成员。using-directive不得出现在类作用域中,但可以出现在命名空间作用域或块作用域中。[注意:在使用using指令中查找命名空间名称时,仅考虑命名空间名称,详见3.4.6。]
using namespace
将对现有查找方式产生相当多的副作用。特别是,它必须在检查特定类作用域和检查封闭命名空间之间的某个时刻执行。也就是说:1)合并类级别和已使用命名空间级别的查找,2)在检查任何其他类作用域之前查找已使用的命名空间 后,3)在检查封闭命名空间之前查找已使用的命名空间,4)与封闭命名空间合并查找。namespace A {
void foo() {}
struct B {
struct foo {};
void f() {
foo(); // value initialize a A::B::foo object (current behavior)
}
};
}
struct C {
using namespace A;
struct foo {};
void f() {
foo(); // call A::foo
}
};
.
namespace A {
void foo() {}
}
void bar() {}
struct base {
void foo();
void bar();
};
struct test : base {
using namespace A;
void f() {
foo(); // A::foo()
bar(); // base::bar()
}
};
.
namespace A {
void foo( int ) { std::cout << "int"; }
}
void foo( double ) { std::cout << "double"; }
struct test {
using namespace A;
void f() {
foo( 5.0 ); // would print "int" if A is checked *before* the
// enclosing namespace
}
};
using
声明完全相同的效果。它不会为此添加任何新值,但另一方面会使编译器实现者查找变得复杂。命名空间标识符查找现在独立于触发查找的代码位置。当在类内部时,如果查找在类作用域中找不到标识符,则会回退到命名空间查找,但这正是在函数定义中使用的相同命名空间查找,没有必要维护新状态。当在命名空间级别找到using
声明时,使用的命名空间的内容将被引入该命名空间以便于涉及该命名空间的所有查找。如果允许在类级别使用using namespace
,则对于完全相同命名空间的命名空间查找,取决于查找从哪里触发,将有不同的结果,这将使查找的实现变得更加复杂而没有额外的价值。无论如何,我的建议是不使用using namespace
声明。这样可以使代码更简单易懂而无需记住所有命名空间的内容。
using
会产生一些隐含的奇怪问题。但是有些库可能会围绕着using
存在而设计。例如,通过在深度嵌套的长命名空间中故意声明事物。glm
就是这样做的,并使用多种技巧在客户端使用using
时激活/呈现功能。 - v.oddouusing namespace std::placeholders
。请参考 http://en.cppreference.com/w/cpp/utility/functional/bind - v.oddounamespace ph = std::placeholders;
- David Rodríguez - dribeas这可能会被禁止,原因是 开放性 与 封闭性 的对立。
将命名空间引入类会导致有趣的情况,比如:
namespace Foo {}
struct Bar { using namespace Foo; };
namespace Foo {
using Baz = int; // I've just extended `Bar` with a type alias!
void baz(); // I've just extended `Bar` with what looks like a static function!
// etc.
}
namespace Foo
到所有代码的搜索顺序中,就像在每个内联成员函数体中放置该行一样,但它也会对大括号或等于初始化器等起作用。但它仍然会在闭合大括号时过期,就像成员函数体内的using namespace
一样。现在,不幸的是,在不污染封闭命名空间的情况下,在大括号或等于初始化器中使用Koenig-with-fallback查找似乎没有任何方法。 - Ben Voigt我认为这是语言的缺陷。您可以使用以下解决方法。谨记此解决方法,可以轻松地针对语言更改时的名称冲突解决提出规则。
namespace Hello
{
typedef int World;
}
// surround the class (where we want to use namespace Hello)
// by auxiliary namespace (but don't use anonymous namespaces in h-files)
namespace Blah_namesp {
using namespace Hello;
class Blah
{
public:
World DoSomething1();
World DoSomething2();
World DoSomething3();
};
World Blah::DoSomething1()
{
}
} // namespace Blah_namesp
// "extract" class from auxiliary namespace
using Blah_namesp::Blah;
Hello::World Blah::DoSomething2()
{
}
auto Blah::DoSomething3() -> World
{
}
你不能在类内使用 using namespace
,但是你可以简单地使用 #define
,然后在结构体内使用 #undef
。它将与 namespace a = b;
完全相同。
struct foo
{
#define new_namespace old_namespace
void foo2()
{
new_namespace::do_something();
}
#undef new_namespace
};
using namespace
的语法。C# 允许在文件范围内进行类似的操作。而 C++ 的using namespace
则允许将一个命名空间嵌入到另一个命名空间中。 - Billy ONeal