iam*_*ind 77 c++ namespaces using language-lawyer
class C {
using namespace std; // error
};
namespace N {
using namespace std; // ok
}
int main () {
using namespace std; // ok
}
Run Code Online (Sandbox Code Playgroud)
编辑:想知道背后的动机.
Bil*_*eal 30
我不确切知道,但我的猜测是允许在课堂范围内这可能导致混淆:
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?
}
Run Code Online (Sandbox Code Playgroud)
由于没有明显的方法这样做,标准只是说你做不到.
现在,当我们讨论命名空间范围时,这不会引起混淆:
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.
}
}
Run Code Online (Sandbox Code Playgroud)
Ada*_*eld 17
因为C++标准明确禁止它.从C++03§7.3.4[namespace.udir]:
using-directive:
using namespace ::opt nested-name-specifieropt namespace-name ;
一个using指令将不会出现在类范围,但可能会出现在命名空间范围或块的范围.[注意:在using-directive中查找namespace-name时,只考虑名称空间名称,请参阅3.4.6.]
为什么C++标准禁止它?我不知道,要求ISO委员会成员批准语言标准.
我认为理由是它可能会令人困惑.目前,在处理类级别标识符时,lookup将首先在类范围内搜索,然后在封闭的命名空间中搜索.允许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
}
};
Run Code Online (Sandbox Code Playgroud)
.
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()
}
};
Run Code Online (Sandbox Code Playgroud)
.
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
}
};
Run Code Online (Sandbox Code Playgroud)
using在命名空间级别应用声明具有完全相同的效果.它不会为此添加任何新值,但另一方面会使编译器实现者的查找复杂化.命名空间标识符查找现在独立于触发查找的代码中的位置.在类中,如果查找在类范围内找不到标识符,它将回退到命名空间查找,但这与函数定义中使用的命名空间查找完全相同,不需要维护新状态.当using声明是在命名空间层次中,该内容使用的命名空间被带到到该命名空间为所有涉及的命名空间查找.如果using namespace在类级别允许,则根据触发查找的位置,对完全相同的命名空间进行命名空间查找会有不同的结果,这将使查找的实现更加复杂,无需额外的值.无论如何,我的建议是不要使用using namespace声明.它使代码更容易理解,而不必记住所有名称空间的内容.
由于开放性与封闭性,这可能是不允许的。
将名称空间导入到类中会导致类似这样的有趣情况:
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.
}
Run Code Online (Sandbox Code Playgroud)