0

我很容易养成了在标准标识符前面加上前缀std::而不是在using namespace std;. 但是,我已经开始接触 C#,并且我注意到添加任何必要的 using 指令是非常正常的,即,您会看到:

using System;
Console.Write("foo");

代替:

System.Console.Write("foo");

显然,正如我从关于这个主题的 C# 问题中发现的那样,这种用法来自于这样一个事实,即 C# 中的各个系统命名空间比 C++ 中的要小得多std,因此消除了与名称冲突相关的问题,因为有很多可能性较小(如果库使用名称冲突进行更新,您可以将其替换为完全限定名称),并消除与出现大量 Intellisense 选项相关的问题,因为名称空间小到足以处理。

那么问题是,如果这些是在 C# 中使用 using 指令的长期理由,那么 C++ 是否也是如此?将其应用于较小的第三方命名空间以及您自己的较小命名空间通常可以接受吗?

现在我意识到这可能会引起一些争议,我想借此机会要求它不会变成争论。一个好的答案应该包括一个基础,即优点或缺点,以及如何使用一种方式而不是另一种方式真正产生有价值的差异。

我问这个的原因是为了澄清这个问题,并可能消除在 C++ 中使用指令必须是一件坏事的观念。当然,如果需要,可以使用命名空间别名来减少较长的命名空间名称,如果需要,仍然可以使用完全限定的名称,但有时使用指令可以极大地简化访问某些成员,例如用户定义的文字运算符,据我所知,没有 ADL 的形式,这意味着您要么必须使用 using 指令,要么通过函数语法调用运算符方法,这首先破坏了使用运算符的整个目的。

例如,我有一个命名空间(包括一个表示键盘键的结构,以及作为可读替代访问方式的文字后缀:

"caps lock"_key.disable();

这里的问题是,除非您之前插入了using namespace Whatever;or using Whatever::operator"" _key;,否则代码将无法编译,这对用户来说是个坏消息。

使用指令在涉及或在标头中以这样的方式使用时会出现明显的问题std,它们会为该标头的用户带来不需要的额外内容,但是当包含在比包含标题?由于不必每次都键入每个限定符而节省的击键确实加起来了,并且借助当今的 Intellisense 功能,找出不合格标识符属于哪个命名空间就像将鼠标悬停在它上面一样容易。

4

1 回答 1

2

我认为在 C++ 中使用声明的规则相当简单:

  1. 永远不要写“使用命名空间任何东西;” 在头文件的全局范围内,尤其是可能被其他程序重用的头文件(例如,在编写库时)。它用这个命名空间的符号污染了所有后续标头的全局范围,这违背了命名空间的全部目的,并且可能在以后产生不可预见的名称冲突。
  2. 在 .cpp 文件和标头的内部范围(例如内联函数范围)中,您可以“使用”您想要的任何名称空间,因为它不会影响任何其他文件。只需做任何对您来说更方便的事情,并尝试在项目中保持合理一致。

编辑:对于 _key 问题,只需在其自己的命名空间中定义此运算符并告诉用户导入它。这样他们就不需要输入操作符声明。

namespace something {
class key { ... };
}
namespace key_suffix {
something::key operator"" _key() { ... }
}

// user code
void some_function() {
    using namespace key_suffix;
    "caps lock"_key.doSomething();
}
于 2012-09-04T04:09:22.607 回答