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
}
编辑:想知道背后的动机。
Answers:
我不清楚,但是我的猜测是在类范围内允许这样做可能会引起混乱:
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.
}
}
using namespace Hello;
其他内部namespace
(并声明其extern
内部的功能)。
Hello::World Blah::DoSomething()
或Blah::World Blah::DoSomething()
(如果允许),则不认为成员函数定义的返回类型在该语言的类范围内,因此必须对其进行限定。考虑using
用typedef Hello::World World;
at类范围替换at的有效示例。因此,那里应该没有惊喜。
因为C ++标准明确禁止使用它。从C ++ 03§7.3.4[namespace.udir]:
使用指令: 使用命名空间:: opt 嵌套名称说明符opt namespace-name ;
一个using指令将不会出现在类范围,但可能会出现在命名空间范围或块的范围。[注意:在using指令中查找名称空间名称时,仅考虑名称空间名称,请参阅3.4.6。]
为什么C ++标准禁止它?我不知道,请问批准语言标准的ISO委员会成员。
我认为,这样做的理由可能是令人困惑的。当前,在处理类级别标识符时,查找将首先在类范围内搜索,然后在封闭的名称空间中搜索。允许using namespace
at类级别将对现在如何执行查找产生相当大的副作用。特别是,它必须在检查特定类范围和检查封闭名称空间之间的某个时间执行。那就是: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
存在的事实进行设计。通过故意在深层嵌套的长名称空间中声明事物。例如glm
,这样做,并在客户端使用时使用多种技巧来激活/呈现功能using
。
using namespace std::placeholders
。cf en.cppreference.com/w/cpp/utility/functional/bind
namespace ph = std::placeholders;
由于开放与封闭,这可能是不允许的。
将名称空间导入到类中会导致如下有趣的情况:
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 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
。C#允许类似的内容,但仅在文件范围内。C ++using namespace
允许您将一个名称空间合并到另一个名称空间中。