(转) [C++]我再也不想在任何头文件中看到using namespace xxx这种句子了(译)
原文的传送:I don’t want to see another “using namespace xxx;” in a header file ever again
转自 http://blog.csdn.net/pleasecallmewhy/article/details/8528702
在这里,我毫不回避地说了这句话。
作为一个开发者/团队领导者,我经常会去招聘新的项目成员,有时候也帮助其他组的人来面试应聘者。作为应聘流程之一,我经常要求应聘者写一些代码,因此我检查过相当多的代码。在最近提交的 C++ 代码中,我注意到一个趋势,在任何头文件中,我总是能看到以下代码:
using namespace std;
如果我用我们的代码检查系统(在实践中我十分推荐这个系统)来检验代码,以上那行代码经常会跟着一句评论“Timo 不会这样写的”。他们说得很对,我确实不会这么写。
那么,为什么我说服了很多 C++ 教材(也许并不是什么好事),让他们认为使用上面那段代码是非常坏的方式?让我们先来看看上面那段代码做了什么。总的来说,它把命名空间“std”以内的所有内容(或者其他由作者用 using 调用命名空间)无一例外的引入了目前的命名空间中。请注意我说的“所有内容”,并不是一两个你想用的类\类型\模板。在一段代码的开头引入命名空间的原因则是加强程序模块化,和减少命名冲突。大体上,它允许你可以写类似下面的那段代码,并且保证编译器可以选择正确的实现:
std::vector<std::string> names;
my_cool_reimplementation::vector<our_internal_stuff::string> othernames;
现在,假定我们正在尝试减少代码输入,并且在以上代码中使用 using 声明(或者更糟糕的,两个命名空间都声明了),按照如下代码来实现:
std::vector<std::string> names;
my_cool_reimplementation::vector<our_internal_stuff::string> othernames;
如果这段代码的作者很幸运的话,编译器会选择 vector 的正确实现,或者至少在最初的阶段会这么做。但是过了一段时间,你会碰到一些很奇怪的编译器错误。幸运的话,你能找到这些错误的原因——我曾经遇到过类似问题,我花费了好几天才能找到这类问题的原因。该死,它们会浪费你很多的时间,仅仅因为你为了想少打 5 个字符的代码。
并且,如果你把 using 声明用在了头文件中,你会让这类问题更加恶化,因为命名冲突问题早晚都会在一个调用关系非常非常远的模块中神不知鬼不觉的出现,而你可能需要查三层调用才可以找到原因所在,一个头文件包含了另一个直接使用 using 声明的头文件可以导致命名空间被立刻污染掉,任何一个使用命名空间的文件如果使用了 std 命名空间的内容,都会导致这类问题。
那么,为什么你能在很多教科书中看到它们使用 using namespace std? 我的理论是,它确实会帮助改善整本书的排版,并且能减少一些视觉的混乱。在一本纸质书中,你只有很有限的空间来写文字,因此你必须最大限度的利用它,加之书中的代码例子通常都很简单。但另一方面,不同的命名空间限定符会带来了很多视觉混乱,这会让读者很难从上下文判断作者的意图。当你想在这个时代写一些有效率的代码的时候,以上两点都不完全对,现在的编译器大多数能每行处理 60-80 个单词(你可以试试,这可以的)。因此,不要乱引入命名空间。
如果你非常明确的想在一个头文件中使用 using 声明,应该怎么做?我们有其他途径可以减少不得不用 using 声明的情况——你可以用以下其中一种,或则多种方式的组合。
首先,你只需使用 typedef。我会建议你使用这种方法,即使我并不经常遵循我自己的建议,我也认为无论如何这都是一个在实际应用中很好的方法。实际上,使用 typedef 有两个好处——他让一个类型名可读性增加,如果你选择了一个很好的名字,它可以让作者的意图更加显而易见。比较一下如下的声明方式:
std::map<std::string, long> clientLocations;
typedef std::map<std::string, long> ClientNameToZip;
ClientNameToZip clientLocations;
第二个声明——即使它被展开为两行——也比第一个声明更加直观,同时,它也避免了命名空间模糊化。
另外一个选择则是用两种方法来限制 using 声明的作用域——仅仅是你想用的那个“using”符号,例如:
- 但是,把这段声明扔到头文件中,几乎和使用“using namespace”一样糟糕,因此,你应该使用作用域来限制下它的可见性,来确保你的 using 声明真的只在第一次做 using 声明的地方有效。例如,你可以用如下方法限制类声明作用域:
namespace bar
{
struct zzz
{
…
};
}
class foo
{
using namespace bar;
zzz m_snooze; // Pulls in bar::zzz };
或者,你可以直接把 using 的作用域限制到一个函数中,例如:
void temp ()
{
using namespace std;
string test = "fooBar";
}
不管哪种方法,你都可以把 using 的作用域限制到需要使用它的代码中,而不是把它放到代码的公共空间中。你的工程越大,确保模块化,和最小化不可预料的负面影响就显得越发重要。
(转) [C++]我再也不想在任何头文件中看到using namespace xxx这种句子了(译)的更多相关文章
- ZT 头文件包含其实是一想很烦琐的工作 第一个原则应该是,如果可以不包含头文件
当出现访问类的函数或者需要确定类大小的时候,才需要用头文件(使用其类定义) http://blog.csdn.net/clever101/article/details/4751717 看到这个 ...
- 为什么我再也不想和 Google HR 交谈了
英文:yegor256,编译:伯乐在线/心灵是一棵开花的树 http://blog.jobbole.com/110340/ [伯乐在线导读]: 关于程序员面试时现场写代码,估计大家还记得 2015 年 ...
- spring data mongodb中,如果对象中的属性不想加入到数据库字段中
spring data mongodb中,如果对象中的属性不想加入到数据库字段中,可加@Transient注解,声明为透明属性 spring data mongodb 官网帮助文档 http://ww ...
- git中提交了想要忽略的文件,如何在删除
我们在用git的时候,有时会不小心将不需要文件跟踪的文件(如.classpath文件.project等)提交到git的服务器,这时候要忽略这些文件的做法是: 1.修改.gitignore文件 按照规则 ...
- 想在don‘t starve中活的更久?那饥荒海难攻略你怎么能不知道!
饥荒海难mac版是一款非常好玩的烧脑游戏.玩家将扮演一个勇敢的绅士科学家威尔逊,被一个恶魔困住并送到一个神秘的荒野世界,玩家必须利用异世界中的自然资源让自己存活下去,并且抵御各种异世界生物的威胁.想在 ...
- Eclipse 想运行一个java文件,结果却运行了另外一个
参考: Eclipse 想运行一个java文件,结果却运行了另外一个_小鹰信息技术服务部-CSDN博客_eclipse怎么运行另一个
- 作为程序员,再也不想和PM干架了
上周,又看见有程序和PM(产品经理)吵了起来,大致是因为晚上就要上线了,下午的时候PM来说要改点需求,但程序不愿意.兴许是天气热了,大家都很烦躁,于是一言不合就发飙了,最终还是程序老大介入才解决了问题 ...
- 想要将我们的OSGi框架中的批量日志单独打印到文件中
我们的日志虽然没有直接依赖logback,但遗憾的是也没有使用slf4j,而是使用了Apache Common-Logging slf4j 和 common-logging有什么区别呢 common- ...
- Django 想要单独执行文件
Django 单独文件执行 文件 我是在项目根目录文件创建的. 配置文件: #!/usr/bin/env python import os import sys if __name__ == & ...
随机推荐
- layui 单选框选中事件
<div class="layui-form-item" pane=""> <label class="layui-form-lab ...
- scrapy框架中Spiders用法
scrapy框架中Spiders用法 Spider类定义了如何爬去某个网站,包括爬取的动作以及如何从网页内容中提取结构化的数据 总的来说spider就是定义爬取的动作以及分析某个网页 工作流程分析 以 ...
- [BZOJ3128]a+b Problem
题解 最小割+主席树优化建图 首先看到每个点只有\(0/1\)两种状态就想到最小割 然后由于有一个限制是点\(i\)是黑点且有符合条件的白点就会减去\(p_i\) 所以我们将\(S\)集合设为黑点集合 ...
- A.走方格
链接:https://ac.nowcoder.com/acm/contest/368/A 题意: 在一个n*n的方格中,你只能斜着走. 你还有一次上下左右走的机会 给你一个起点(sx,sy),和终点( ...
- c#学习系列之跳出循环 break,continue
break是完全跳出循环: ) { ) break; Console.WriteLine(a++); } 此处输出1,2,3,4,5,6,7,8 continue是跳出当前的循环: ;i<=;i ...
- [已读]精通AngularJS
觉得可以看第二遍,内容其实还不错啦,就是翻译会有点生硬.
- Unity Shader入门精要学习笔记 - 第11章 让画面动起来
转自 冯乐乐的 <Unity Shader入门精要> Unity Shader 中的内置变量 动画效果往往都是把时间添加到一些变量的计算中,以便在时间变化时画面也可以随之变化.Unity ...
- 删除所有约束、表、视图等SQL脚本
--删除所有约束.表.视图等SQL脚本 --############################################### --删除所有外键约束 --################# ...
- 分享一套Code Smith 搭建N层架构模板
开篇 平常开发时,由于冗余代码过多,程序员做重复的工作过多势必会影响开发效率.倘若 对重复性代码简单的复制.粘贴,虽然也能节省时间,但也需仔细一步步替换,这无疑也是一件费力的事.这时我们急需代码生成工 ...
- MySql数据库的相关操作
SQL(Structred Query Language)结构化查询语言:和数据库交互的语言,进行数据库管理的语言. 一.数据库的操作: 1.查询所有数据库: show databases; 2.创建 ...