为什么C++中没有撤销“using”的方法?

9
我经常发现自己想要一种撤销使用语句的效果或包含所有命名空间(如std),但排除要替换的部分(如cout)的方法。出于某种原因,这是不可能的。我想知道为什么决定不将此功能添加到语言中?是否有技术上的原因?我认为这不仅仅是因为它被遗忘了,因为它似乎也没有被列入C++0x的计划中。
只是为了澄清,我不是在寻找解决方法,因为谷歌可以显示给我。我正在寻找为什么这是不可能的解释,以及为什么(据我所知)它没有被考虑纳入0x中。

2
我想提醒你,using namespace 指令通常被认为是一个非常糟糕的主意,你可以完全使用每个经常使用的名称一个 using 指令... 而且坦白地说,我通常不会费心去打命名空间(又有什么关系呢?)。 - Matthieu M.
澄清一下:您不想在文件的某个后期撤销using声明的效果;您想要在using声明本身中指定要排除的符号吗?我觉得您在这里选择的措辞有些令人困惑。 - Owen S.
@msteam:您是否知道编写 using 指令不仅可以在文件作用域内,还可以在函数或嵌套块内? - fredoverflow
@owen:拥有撤销的能力是理想而且更为通用,但是在编译器中实现排除特定名称的能力仍然很有用并且更易实现。 - mstearn
@Matthieu "boost::" <- 这是7个字符 =) - Viktor Sehr
@Viktor:我在谈论std::,你总是可以使用别名 =) - Matthieu M.
3个回答

11

使用指令将名称或一组名称引入给定的声明作用域。

出于同样的原因,您无法“取消使用”,就像您无法说

int x = 42;
// and later
[remove name x somehow]

在C++中,无论这些名称来自哪里,都没有办法从作用域中取消引用名称。

考虑到这会使名称查找过于复杂(因为名称既可以添加又可以从作用域中删除),除非存在真正强烈的使用案例,否则不太可能被视为潜在的语言特性。


4
如果你只需要在少数几个地方使用特定的命名空间,那么你就不会在一开始使用 using,因为它会应用于整个作用域。相反,你可以手动给每个要使用该命名空间的地方添加命名空间前缀。请注意保持原意,使翻译内容易于理解。 - casablanca
在作用域中不允许删除或替换名称有一个很好的技术原因:链接。命名空间::x的混淆形式只能引用单个地址。但是,这并不适用于被拉入命名空间的名称,因为它们仍将与其原始命名空间一起混淆。这不会使查找变复杂。如果像其他语言中一样,“using namespace std except (cout, cerr);”是可能的,那么这些名称永远不会出现在当前命名空间中,因此不需要删除它们。 - mstearn
@mstearn:using 指令与链接没有任何关系;它们只影响名称查找。它们实际上不会向声明作用域添加任何东西(函数或对象),它们只允许将它们视为在该声明作用域中。无论如何,这确实没有一个好的使用案例,这意味着它不会被考虑作为潜在的语言特性(尽管谁知道:一些如std::error_code之类的特性已经进入了C++0x,而我认为这确实没有一个特别好的用例,至少不是以它的实现方式)。 - James McNellis
没错,这就是为什么"int x"和"using some::x"之类的东西在本质上是不同的。 - mstearn

2
这是因为using指令不适用于本机C++代码。它的目的是帮助将C代码迁移到C++。在这种情况下,“取消使用”没有意义。
-编辑- 我应该更明确一些。在这种特定情况下,看起来mstearn正在使用using指令全局包含std命名空间。这样做通常是一个坏主意,因为它会导致全局命名空间污染,并且只应在某些情况下执行,例如从另一种语言转换到C++。
在其他情况下,利用using指令是可以的(在函数内,命名空间组合中)。然而,在这些情况下,“取消使用”也没有意义。

1
我不太确定这句话的意思。也许您可以澄清一下,您所说的“using directives不应该被使用”是什么意思? - James McNellis
@James McNellis 好主意 (+1) - aCuria
@James McNellis,除了现有代码可能与新用法冲突并且您可能想要将其包装在命名空间中之外,没有什么好的理由使用“using std,cout”而不是“std :: cout”。 - Martin Beckett
1
@James - 我猜 'using' 的理由是为了防止人们抱怨他们美丽简洁的 C 语言变得像 Java(或 Cobol)一样冗长! - Martin Beckett
@aCuria - 应避免使用_Global_ using指令,但_local_(函数作用域)using指令可以提高可读性(可以说),如果没有它们,命名空间将不会比仅有名称前缀更好。 (嗯,不完全是这样,因为它们仍然对于模板中的ADL非常有用,但是那些情况的数量非常少。) - Mankarse
显示剩余2条评论

1
主要是因为有一些解决方法非常简单明了,包含一个特定目的的“功能”几乎没有任何好处。虽然我不确定他是否直接表述过,但我认为在设计C++时的指导方针之一始终是更喜欢通用机制而不是特定目的的机制,因此使用现有的作用域系统(例如)比添加一些特殊的方法来从作用域中删除已经引入的内容更有意义。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接