使用 C++ 命名空间时,您是否更喜欢显式命名它们,如下所示:
std::cout << "Hello, world!\n";
还是您更喜欢using namespace
:
using namespace std;
cout << "Hello, world!\n";
如果您更喜欢后者,您是否在文件或函数范围内声明您的使用?
就我个人而言,我更喜欢明确地命名它们——它的类型更多,但是当使用混合命名空间(例如std
和boost
)时,我发现它更具可读性。
使用 C++ 命名空间时,您是否更喜欢显式命名它们,如下所示:
std::cout << "Hello, world!\n";
还是您更喜欢using namespace
:
using namespace std;
cout << "Hello, world!\n";
如果您更喜欢后者,您是否在文件或函数范围内声明您的使用?
就我个人而言,我更喜欢明确地命名它们——它的类型更多,但是当使用混合命名空间(例如std
和boost
)时,我发现它更具可读性。
我总是使用明确的。写 std 不会伤害我,我清楚地看到它来自哪里。当您有一些遗留项目需要使用它自己的“字符串”、“向量”等来维护时,它会很有用。代码携带的信息越多越好。
额外的输入不是这里的问题。显式限定名称的问题是视觉混乱。让我们面对现实吧,C++ 语法是杂乱无章的。无需通过不必要地延长名称并在代码中大量使用::
s 来使情况变得更糟。
我和 Jeff Atwood 在一起:最好的代码就是没有代码。这是真的。
命名空间导入是减少混乱的好方法,没有任何缺点:只要打开的命名空间的范围减少到单个编译单元1,如果出现名称冲突,就可以轻松解决。
为什么显式名称应该(通常)更具可读性对我来说一直是个谜。读者通常应该对代码足够了解,以便能够推断出语义。如果不是,则代码无论如何都需要修复。
1)推论:没有using
标题!
我总是using namespace
用于标准和提升。其他一切我倾向于使用显式命名空间,除非它使用得太多以至于会使代码混乱。
在标头中,我从不使用using namespace
以避免污染#include 源的全局命名空间。
我的一般规则是始终在标头中显式使用命名空间,并且通常在代码中使用 using。前者的原因是在定义的每个部分中明确说明正在使用什么,而后者的原因是如果有必要,它可以很容易地使用来自另一个命名空间的替换。即,如果我们想开始使用 foo::string 而不是 std::string,我们只需要更新标头和 using 语句,而不是在代码中用 foo::string 替换 std::string 的每个实例。
当然,这对于驻留在 std:: 命名空间中的类不太有用,因为即使您替换了一个类,您仍然可能在 std 中使用其他类,并且可能会遇到歧义问题,但这只是一个示例。
using
并且using namespace
对于使代码更具可读性非常有用 - 消除混乱。
但在任何情况下,如果很难找出符号的来源,我拒绝导入它的整个命名空间。
我尝试限制导入命名空间的范围:
void bar() {
// do stuff without vector
{ using std::vector;
// do stuff with vector
}
// do stuff without vector
}
对于“众所周知”的库,比如std
,我敢于使用using namespace std
. 有理由相信阅读此代码的每个人都知道这些符号。
作为旁注,该using
关键字还用于指示派生类还导出其超类的重载成员。
class A {
void f( A );
void f( bool );
};
class B : public A {
using A::f; // without this, we get a compilation error in foo()
void f(bool);
};
void foo() {
B b;
b.f( A() ); // here's a compilation error when no `using` is used in B
}
当有一些歧义时,我只使用显式命名空间。它更具可读性,但是额外的输入太乏味了,并且您必须假设其他开发人员对标准库具有基本的熟悉程度。
我拼写命名空间的唯一其他时间是我只使用它一次或两次,例如添加快速调试语句,或者我正在使用一些非标准库。
我通常在文件范围内声明命名空间,但如果您正在混合命名空间,则将声明放在更接近使用它的点(在函数范围内)可能是有意义的。
using
在函数范围内,或者如果函数非常小(通常是),只需显式命名空间
我倾向于在 .cpp 文件的顶部显式导入我需要的名称,所以......
使用 std::cout;使用 std::endl;
ETC...
这样我就可以控制我使用的名称,并且很容易看到它们的来源,并且代码在使用时不会混乱。
在我使用来自不同命名空间的两个名称的极少数情况下,我会在使用时完全限定它们。
我总是在标题中使用完全限定的名称,并且几乎从不在任何地方使用“使用命名空间 x”...