尽可能避免在头文件使用using namespace(转载)

做为一个开发者/团队领导者,我常常会去招聘新的项目成员,有时候也帮助其余组的人来面试应聘者。做为应聘流程之一,我常常要求应聘者写一些代码,所以我检查过至关多的代码。在最近提交的C++代码中,我注意到一个趋势,在任何头文件中,我老是能看到如下代码:面试

usingnamespace std;

若是我用咱们的代码检查系统(在实践中我十分推荐这个系统)来检验代码,以上那行代码常常会跟着一句评论“Timo不会这样写的”。他们说得很对,我确实不会这么写。模块化

那么,为何我说服了不少C++教材(也许并非什么好事),让他们认为使用上面那段代码是很是坏的方式?让咱们先来看看上面那段代码作了什么。总的来讲,它把命名空间“std”之内的全部内容(或者其余由做者用using调用命名空间)无一例外的引入了目前的命名空间中。请注意我说的“全部内容”,并非一两个你想用的类\类型\模板。在一段代码的开头引入命名空间的缘由则是增强程序模块化,和减小命名冲突。大致上,它容许你能够写相似下面的那段代码,而且保证编译器能够选择正确的实现:函数

std::vector<std::string> names; my_cool_reimplementation::vector<our_internal_stuff::string> othernames;

如今,假定咱们正在尝试减小代码输入,而且在以上代码中使用using声明(或者更糟糕的,两个命名空间都声明了),按照以下代码来实现:spa

vector<string> names; vector<our_internal_stuff::string> othernames;

若是这段代码的做者很幸运的话,编译器会选择vector的正确实现,或者至少在最初的阶段会这么作。可是过了一段时间,你会碰到一些很奇怪的编译器错误。幸运的话,你能找到这些错误的缘由——我曾经遇到过相似问题,我花费了好几天才能找到这类问题的缘由。该死,它们会浪费你不少的时间,仅仅由于你为了想少打5个字符的代码。code

而且,若是你把using声明用在了头文件中,你会让这类问题更加恶化,由于命名冲突问题迟早都会在一个调用关系很是很是远的模块中神不知鬼不觉的出现,而你可能须要查三层调用才能够找到缘由所在,一个头文件包含了另外一个直接使用using声明的头文件能够致使命名空间被马上污染掉,任何一个使用命名空间的文件若是使用了std命名空间的内容,都会致使这类问题。ip

那么,为何你能在不少教科书中看到它们使用using namespace std?个人理论是,它确实会帮助改善整本书的排版,而且能减小一些视觉的混乱。在一本纸质书中,你只有颇有限的空间来写文字,所以你必须最大限度的利用它,加之书中的代码例子一般都很简单。但另外一方面,不一样的命名空间限定符会带来了不少视觉混乱,这会让读者很难从上下文判断做者的意图。当你想在这个时代写一些有效率的代码的时候,以上两点都不彻底对,如今的编译器大多数能每行处理60-80个单词(你能够试试,这能够的)。所以,不要乱引入命名空间。作用域

若是你很是明确的想在一个头文件中使用using声明,应该怎么作?咱们有其余途径能够减小不得不用using声明的状况——你能够用如下其中一种,或则多种方式的组合。开发

首先,你只需使用typedef。我会建议你使用这种方法,即便我并不常常遵循我本身的建议,我也认为不管如何这都是一个在实际应用中很好的方法。实际上,使用typedef有两个好处——他让一个类型名可读性增长,若是你选择了一个很好的名字,它可让做者的意图更加显而易见。比较一下以下的声明方式:get

std::map<std::string,long> clientLocations;
typedef std::map<std::string,long>ClientNameToZip;
ClientNameToZip
clientLocations;

第二个声明——即便它被展开为两行——也比第一个声明更加直观,同时,它也避免了命名空间模糊化。编译器

另一个选择则是用两种方法来限制using声明的做用域——仅仅是你想用的那个“using”符号,例如:

using std::string;

可是,把这段声明扔到头文件中,几乎和使用“using namespace”同样糟糕,所以,你应该使用做用域来限制下它的可见性,来确保你的using声明真的只在第一次作using声明的地方有效。例如,你能够用以下方法限制类声明做用域:

namespace bar {
  struct zzz {};
}
class foo {
  usingnamespace bar;  zzz m_snooze;// Pulls in bar::zzz
};

或者,你能够直接把using的做用域限制到一个函数中,例如:

void temp()
{
  usingnamespace std;
  string
test ="fooBar";
}

无论哪一种方法,你均可以把using的做用域限制到须要使用它的代码中,而不是把它放到代码的公共空间中。你的工程越大,确保模块化,和最小化不可预料的负面影响就显得愈加重要。

原文:I don’t want to see another “using namespace xxx;” in a header file ever again

相关文章
相关标签/搜索