科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道C++5×5断想之五:我之C++拍案惊奇

C++5×5断想之五:我之C++拍案惊奇

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

在本系列第五也是最后一篇文章里,我将选出让自己拍案惊奇、豁然开朗的五个时刻。

作者:Scott Meyers 来源:CSDN 2007年9月24日

关键字: ghost C++ 断想

  • 评论
  • 分享微博
  • 分享邮件

在本页阅读全文(共2页)

作者介绍

Scott MeyersC++顶级权威之一,为世界各地客户提供培训和咨询服务。发表有畅销的Effective C++系列图书(《Effective C++》、《More Effective C++》和《Effective STL》),设计了创新型的Effective C++ CDAddison WesleyEffective Software Development Series顾问编辑,The C++ Source (http://www.artima.com/cppsource/)咨询板块专家。布朗大学计算机科学博士,他的网站是www.aristeia.com  

 

 

在本系列第五也是最后一篇文章里,我将选出让自己拍案惊奇、豁然开朗的五个时刻。

如果你从事某项工作的时间足够长,必然有几次在疑窦丛生的同时,忽感豁然开朗的经历(如果没有过,那你肯定是入错行了)。每当这些时刻来临的时候,我都惊得呆了,禁不住大口吸气;好像原来只见黑白二色,突然穿越了时空,来到一个五光十色的世界。最后我慢慢回过味来,面带微笑。如此时刻让人激动。疑窦烟消云散,洞明取代了它的位置。

这样的事情在1978年就出现过一次。经过长期的煎熬,有一天我突然明白了指针的工作原理——如果说软件学习之路上也有成年礼的话,那它就是吧。但我那时还在使用Pascal编程,因此不能将它列入这个和C++相关的名单。现在公开我的选择吧:

 

认识到C++中特殊成员函数可以声明为private[注释1]1988年。和很多朋友一样,那时我正在自学C++。某天,刚毕业的同事John Shewchuk跑到我的办公室问我,“如果得到一个不可拷贝对象?”在场的有好几个人,但都不知如何回答。我们知道,如果不定义拷贝构造函数和拷贝赋值操作符,那么编译器会自动加入,最后得到的对象是可拷贝的。若要阻止编译器自动生成,我们就必须手工定义,但这样一来,对象还是可拷贝的。就像Grinch[注释2]一样,我们个个迷惑不解,没有人能找到解决办法。

后来(可能是当天或第二天,我记不清了),John宣称自己有了解决办法:将拷贝构造函数声明为private就搞定了。现在看来,这个问题是多么简单啊!但当时对于我们来说,不蒂于发现了新大陆;这是我们对C++知识融会贯通的重要一步。三年后,我出《Effective C++》第一版时,将这个简单的发现供奉在一个独立的条款(不到一页,大概是这本书中最短的条款)里。再后来,我愈加意识到这个发现的重要性,因此在《Effective C++》的后面两版中都写了进去。1988年,我不觉得这种用private阻止编译器隐式生成函数的方法显而易见;现在是2006年,我还是这么认为。

 

理解Barton Nackman在单位分析(译者注:Dimensional Analysis。更学术化的叫法是量纲分析)法中提出的无类型模板参数non-type template parameters的用法1995年。19885月,我在《IEEE Software》上读到Robert F. CmelikNarain H. Gehani合著的一篇文章——《Dimensional Analysis with C++》。他们提出了一种在物理单位(如长度、速度和时间等)的计算过程中检测单位错误的方法。比如,用长度除以时间,再将结果和一个速度量比较是正确的,但和加速度量(它由长度除以时间的平方得来)比较就错了。CmelikGehani提出,可以将单位信息存储到对象中,然后在运行时进行错误检测。这种方法将使对象变大,而且耗费运行时间。我觉得应该有更好的办法,但折腾再三也没有结果,后来就不了了之。

John J. BartonLee R. Nackman在他们1994年出版的《Scientific and Engineering C++》(Addison-Wesley出版社)中提出了一个很好的单位问题解决方案。不过,虽然我当时也拿到了这本书,却没有注意到该项成果——老实说,这本书写得太糟糕了点,我开了个头就扔到一边。直到1995年,我通读了BartonNackman发表在《C++ Report》上的专栏文章,他们这次用通俗易懂的语言描述了自己的方案。结果给我留下了三方面深刻印象。第一,它涵盖了单位的所有可能组合,而不仅仅以命名为依据的组合,因为命名是不完全的。例如,我们将长度除以时间的结果命名为速度,还将压力除以长度的平方的结果命名为压强,但却没有给长度乘以时间的平方再除以角速度的立方的结果一个名份。至少我不知道。即便计算中产生了迄今为止还用不到的单位组合,B&N方案也会确保单位分析的正确性。

第二是B&N方案的运行时消耗:没有。对象没有变大,程序也没有变慢。因此可以说B&N方案是无本而万利[注释3] 。这才是我真正感兴趣的组合方式。

不过最让连连称奇的,还是他们对无类型模板参数(代表各种基本单位的指数式)及其上算术指令(计算结果单位类型)的使用 [注释4]。这样,他们不仅解决了多年前搞得我兴趣索然的实际问题,而且使用的还是一项C++特性(即无类型模板参数。它在那以前引发了我无穷的好奇心)。

直到今天,我还为BartonNackman的成果激动。原本打算将他们在《C++ Report》上的文章列入我的“C++历史上最重要文献”名单,但后来我发现它影响甚微——很少有人像我那样认为他们的成果具有重大意义。现在,我觉得自己有点可耻,因为我只顾自己满足,却没有将好东西与更多人分享。

 

理解Visitor模式的涵义19961997年。命名恰当,是软件工程的一个基本原则。这儿就有一个例子,充分说明了糟糕的命名会多么折磨人。我没觉得Visitor模式的设计机理有什么特别问题,但就是一直弄不明白它的意义。我无法将支离破碎的认识融会贯通。直到后来有一天,我终于明白:Visitor模式和“访问”毫无关系。其实,它是一种体系设计方法——要求引入新的虚拟行为函数时不必改变原体系的结构。抓住这点后,我一下就理解了这个模式的含义。但其命名于我造成了巨大理解障碍,甚至看了《Design Patterns》(http://www.artima.com/cppsource/top_cpp_books.html#dp)如下的描述后:

Visitor使你不用改变行为操作的元素的类,就可以定义新行为。

这个解释清楚而直接,现在看来很好理解,但我当时就是盯住了模式的名字,总觉得“Visitor”应该和“访问”、“遍历”啥的发生点关系。

出现这种结果,我想有两个可能原因。一是我死心眼,见识短浅,鼠目寸光。再有就可能是这个名字选得过于随意。如果名字本身指的张三,而使用文档上说的却是李四,那么至少一些人——比较执拗的那种——肯定要搞糊涂了。我倾向于后一种解释。

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章