阅读更多

2顶
1踩

编程语言
在这里,我毫不回避地说了这句话:
引用
我再也不想在任何头文件中看到“using namespace xxx;”了

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

using namespace std;


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

那么,为什么我说服了很多C++教材(也许并不是什么好事),让他们认为使用上面那段代码是非常坏的方式?

让我们先来看看上面那段代码做了什么。总的来说,它把命名空间“std”以内的所有内容(或者其他由作者用using调用命名空间)无一例外的引入了目前的命名空间中。请注意我说的“所有内容”,并不是一两个你想用的类\类型\模板。在一段代码的开头引入命名空间的原因则是加强程序模块化,和减少命名冲突。大体上,它允许你可以写类似下面的那段代码,并且保证编译器可以选择正确的实现:

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


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

vector<string> names;
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 std::string;


但是,把这段声明扔到头文件中,几乎和使用“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的作用域限制到需要使用它的代码中,而不是把它放到代码的公共空间中。你的工程越大,确保模块化,和最小化不可预料的负面影响就显得越发重要。

原文:I don’t want to see another “using namespace xxx;” in a header file ever again
来自: 图灵社区
2
1
评论 共 6 条 请登录后发表评论
6 楼 renzhe20092584 2013-07-12 10:06
第二种方法还行
5 楼 dohkoos 2013-06-04 08:54
看仔细哦,是header file(.h),不是代码文件(.cpp)。

讲的很有道理。

其实C++就是从面向过程到面向对象时的畸形产物。
4 楼 saiyaren 2013-01-15 09:35
我看hiphop的代码都using xxx;
你这个有什么理论证明这么写不好嘛?你这么写,不觉得代码很乱吗?冲突在适当范围内解决即可
3 楼 mini_hu 2013-01-15 09:34
看似繁琐,其实很有道理,也很有必要
2 楼 xiangjie88 2013-01-14 22:58
typedef std::map<std::string, long> ClientNameToZip; 
ClientNameToZip clientLocations; 

这样的让人也不爽的很。尤其是那些连基本类型也这样搞的,int -> Money类似这样的
1 楼 bhq10000 2013-01-14 17:42
非常有道理!!!
我们经常被一些书误导。

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • MacPro 迁移至 Mac Mini-M1 与 踩坑 For 后端开发

    最新入手了全新的Mac Mini-M1,之前的主力开发机是17款的Mac BookPro,听说M1性能强劲就想着入手体验一下,这里墙裂建议做开发的同学一定要入16G,最先购买了8-512的版本,Idea和Chorme一开,8G内存可用就剩2G了,...

  • 一个前端开发者的mac装机清单

    我是一名前端开发工程师,最近入手了一台MacBook Pro,之前用的是win10,上面倒是跑着一个mac虚拟机。。对于mac的操作基本还是从零开始。趁机捂着脸赶紧捡起博客!!好久好久没写博客了。。真是要不得!! P.S.mac...

  • Unity2D开发笔记一 动起来

      本职工作是Java服务端开发,但是一直对游戏开发抱有幻想,我仍记得当初填写大学志愿的时候,就是想以后从事游戏开发所以才报考的软件工程专业。不过自己真的懒惰,而且整个大学期间也没有专业的学习过这方面知识...

  • iOS 开发资源汇总 肯定有你想要的资源(Continuously updated)

    写在文前 为什么还要重复造轮子? 我相信在看到这篇文章之前,大家肯定找到了很多iOS资源收集,自学资源,精品资源,开源项目收集,大牛Blog...在这里我想把自己接触iOS这三年以来,所遇到的精品资源加上各个社区...

  • 安卓学习,从初学者到大神

    开发设备 : Mac (作为开发者,我认为入手一台mac还是很有必要的,推荐还是mac pro,这种设备真的是早用早享受,如果你是学生党那么这真的是你对自己非常好的投资,如果你不是,那么我相信你是买得起的,购买渠道...

  • 安卓大神的秘诀

    工欲善其事,必先利其器 ... 开发设备 : Mac(作为开发者,我认为入手一台mac还是很有必要的,推荐还是mac pro,这种设备真的是早用早享受,如果你是学生党那么这真的是你对自己非常好的投资,如果你不是,那...

  • rx550 黑苹果_黑苹果Hackintosh显卡入手指南

    黑苹果Hackintosh显卡入手指南2021-01-05 18:38:2433点赞206收藏18评论你是AMD Yes党?还是intel和NVIDIA的忠实簇拥呢?最新一届#装机大师赛#开始啦!本次装机阵营赛分为3A红组、intel NVIDIA蓝绿组、混搭组还有ITX...

  • 零基础如何学习 iOS 开发?

    作为一名混迹iOS开发圈近4年的码农,资历不深不浅,看到这个问题还是忍不住想回答一下。 如果你打算学习iOS开发,那么在开始学之前,你要做好以下4个方面的准备。 ————————————————————— 1 ...

  • Mac 软件篇

    Mac 下的软件那么多,又是免费又是付费,应该怎么选呢?我来分享下我的推荐列表,推荐的优先级老规矩,从上往下依次降低。 Alfred - 免费,绝对的推荐Top1,很提效率,高级版 Powerpack 售价 £17。除了能快速搜索...

  • iOS 开发怎么入门?

    请问有设计模式、内存管理方面的资料吗?最好有除了官方文档之外的其它内容, 17 条评论  ... 开发工程师 4965 人赞同 这次更新把大多数推荐书籍及网站的图贴了出来,又给大家介绍了很多

  • 【转】iOS 开发怎么入门?

    iOS 开发怎么入门? 请问有设计模式、内存管理方面的资料吗?最好有除了官方文档之外的其它内容,10 条评论 分享 按投票排序按时间排序92 个回答 543赞同反对,不会显示你的姓名郝健宗,曾经的注册会计师,如今鹅...

  • mac安装win10_老笔记本加装1T固态硬盘,顺便安装win10 Mac双系统,真香

    16年的时候淘汰了用了8年的老笔记本,入手了一款游戏本-华硕飞行堡垒FX-PRO,越来越感觉这款老本的性能有点跟不上了, 正赶上去年开始SSD全线降价,于是准备给它加装一个SSD。其实NVMe接口的固态硬盘目前来说性价比...

  • Mac IDA动态调试Android应用dump dex

    由于本人使用的是Mac来做开发,并且最近要做逆向相关,苦于网上多数教程都是Win的,没办法只有到处搜集资料和自己踩坑,摸着石头过河。这里分享一下Mac来做的整个过程。目标,IDA动态调试,dump dex脱壳。 脱壳的话...

  • Android小记:Android入门教程

    工欲善其事,必先利其器 ...开发设备 : Mac (作为开发者,我认为入手一台mac还是很有必要的,推荐还是mac pro,这种设备真的是早用早享受,如果你是学生党那么这真的是你对自己非常好的投资,如果你

  • ANDROID学习之路

    这是Google最新推出的Android开发工具,基于IDEA,编译依赖Gradle,目前已经推出1.0正式版,这是Android开发工具的未来,所以身为Android开发者有必要花点时间去学习使用它,亲身经历,自从使用它之后再也不想去碰...

  • Mac入门技巧及必备软件-推荐收藏(从Windows到Mac的心路历程)

    如果您还在纠结要不要买Mac电脑,如果您是Mac新手,如果您想了解mac使用技巧,请看完此文,一定会有所收获。

  • Android小记:Android学习之路

    没有之一, 所以如果你不差钱的话,强烈建议入手一台Mac,推荐Pro系列, 当然它的价格确实比较昂贵,如果暂时入手有困难,推荐以后手头宽裕的时候再入手吧,会带给你质的体验。(Google的工程师们都在用Mac,应该比较...

  • 基于JavaScript的human-resource-backend后端开发源码设计

    该项目是一款以JavaScript为主语言的HR(人力资源)后端开发源码,集成了Java、CSS、Vue和HTML等多种语言,共计1035个文件。具体文件构成如下:236个Java文件、179个JavaScript文件、104个PNG图片文件、59个CSS文件、56个Vue文件、54个GIF动画文件、42个类文件、41个XML文件、36个SVG文件、35个HTML文件。该后端系统旨在构建一个高效的人力资源管理平台。

  • 基于Java的SpringCloud脚手架及Vue前端设计源码

    该项目是一款基于Java的SpringCloud微服务架构的脚手架,同时融合了Vue前端技术。项目包含131个文件,其中Java源代码文件50个,Vue组件文件19个,JavaScript和HTML/CSS相关文件共计38个,XML配置文件13个,YAML文件8个,JSON文件4个,图片文件3个,Git忽略配置文件2个,Markdown文件2个,HTML文件2个。项目结构清晰,功能完善,适用于快速开发和部署微服务应用。

  • 长治医学院在辽宁2020-2024各专业最低录取分数及位次表.pdf

    那些年,与你同分同位次的同学都去了哪里?全国各大学在辽宁2020-2024年各专业最低录取分数及录取位次数据,高考志愿必备参考数据

Global site tag (gtag.js) - Google Analytics