错误ID:fatalerror99
210113次访问,排名300好友0人,关注者1
还好
fatalerror99的文章
原创 24 篇
翻译 80 篇
转载 5 篇
评论 381 篇
fatalerror99的公告
Copyleft © 2005 - 2008 by fatalerror99 (iTePub's Nirvana)

本 BLog 所有文章除注明转载者外,均为本人原创或翻译,欢迎转载。转载时请保持文章完整并注明出处。

强烈推荐使用 Mozilla Firefox 浏览本 BLog。

MSN: fatalerror9999@hotmail.com

e-mail: kong_kong@163.com

最近评论
七星瓢企鹅:央视的新楼盖起来了,听说北京人照例给他起了个外号叫“大裤衩”
mopyman:严重鄙视此人
turingbook
简直是利欲熏心
psnccs:Wow gold
fdytxz:www.meinv880.cn
www.jipinjiading36.cn
terence zhao:感觉 读到现在,有时候感觉作者一直在作一个假设。然后我们在他们的假设中读书,不过思想还是不错的。
文章分类
收藏
    相册
    Effective C++, 3rd Edition 插图
    数学公式
    不服不行
    Bjarne Stroustrup
    Alexander A. Stepanov
    Andrei Alexandrescu
    Bruce Eckel
    Charles Petzold
    Chris Sells
    David R. Musser
    Dennis M. Ritchie
    Donald E. Knuth
    Herb Sutter
    James Gosling
    Nicolai M. Josuttis
    Scott Meyers
    Stanley B. Lippman
    侯捷
    荣耀
    精点 BLog
    水瓶水蓝
    水瓶水蓝 —— 晃荡在阴阳两界的魂儿
    (RSS)
    CityLife 的流水账(RSS)
    为艺术而技术(RSS)
    乱发当风(RSS)
    微起涟漪 —— basse(RSS)
    暗金色月亮的赫拉迪克宝盒(RSS)
    杏坛雨的博客(RSS)
    王晓渔:书中自有……(RSS)
    开发 BLog
    alai04 的专栏(RSS)
    C++ 的罗浮宫(RSS)
    Coofucoo's Blog--The Unadulterated Coofucoo(RSS)
    GreenCode's Blog(RSS)
    ilovevc 的专栏(RSS)
    lxwde 的专栏(RSS)
    oiramario(RSS)
    ralph623 的专栏(RSS)
    renco 的专栏(RSS)
    Scorpio Auding @ Blog++(RSS)
    SnowFalcon 的专栏(RSS)
    Stan Lippman's BLog(RSS)
    Sutter's (Online) Mill(RSS)
    切尔斯基(RSS)
    周星星 之 Blog(RSS)
    孟岩(RSS)
    开心就好的代码人生(RSS)
    心如止水 —— coofucoo 的专栏(RSS)
    方舟(RSS)
    歌谣在风中飘舞(RSS)
    空谷幽兰,心如皓月 —— 陈皓专栏(RSS)
    艺术编程(RSS)
    透明思考 - 1(RSS)
    透明思考 - 2(RSS)
    陈硕的 Blog(RSS)
    开发网站
    CSDN.NET
    artima devdloper: Best practices in enterprise software development
    Experts Exchange
    IBM DeveloperWorks
    IBM DeveloperWorks 中国(RSS)
    Programmers' Heaven
    The Artima Developer Community
    The Code Project
    卡卡社区
    开发语言与环境
    (CHEZ (CHEZ SCHEME))
    .NET Languages
    PHP: Hypertext Preprocessor
    Eclipse.org home
    Python Programming Language
    REBOL Technologies
    ActiveState
    D Programming Language
    Eclipse Plugins
    Eclipse Plusin Central
    Eiffel Software
    GCL - GNU Common Lisp
    GNU Compiler Collection (GCC)
    Groovy
    IronPython
    Perl
    Ruby on Rails
    Ruby Programming Language
    The Programming Language Lua
    坛子若干
    iTePub
    自由小店 —— iTePub 共建共享电子图书交互平台
    (RSS)
    ChinaJavaWorld.com 技术论坛
    ChinaUnix
    CSDN 技术社区 —— 这个不说大家也知道
    Huihoo - Open Source Community
    ITPUB 论坛
    卡卡社区
    网络书店
    Amazon.com
    China-Pub 网上书店
    joyo Amazon 卓越亚马逊
    第二书店
    有一杯咖啡叫做 Java
    Hibernate
    Java Technology
    JavaWorld
    jGuru
    Spring Framework
    The Apache Software Foundation
    TheServerSide.COM: Your Enterprise Java Community
    有一部经典叫做 C++
    Boost C++ Libraries
    C Programming and C++ Programming
    C/C++ Reference
    cplusplus.com
    Programming in C++, Rules and Recommendations
    The ADAPTIVE Communication Enviroment (ACE)
    The C Standards Committee (ISO C)
    The C++ Standard Committee (ISO C++)
    有一只企鹅叫做 Linux
    Debian
    Fedora Project
    Linux Journal
    Linux Online!
    Linux 伊甸园
    Linux.com
    Red Hat
    SUSE Linux Enterprise from Novell
    The Linux Foundation
    The Linux Kernel Archives
    Ubuntu
    有一种自由叫做开源
    OpenBSD
    CodeGuru
    FreeBSD
    FSF - The Free Software Foundation
    GNU
    Huihoo - Open Source Community
    Open Source Initiative (OSI)
    OpenSolaris
    SourceForge.net
    The Open Enterprise Foundation (OEF)
    专业出版机构
    Addison-Wesley
    APress
    Manning Publications Co.
    McGraw-Hill
    O'Reilly
    Prentice Hall PTR
    Wiley
    Wordware Publishing, Inc.
    Wrox
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    翻译 [翻译] Effective C++, 3rd Edition, Item 37: 绝不要重定义一个函数的 inherited default parameter value(通过继承得到的缺省参数值)收藏

    新一篇: [翻译] Effective C++, 3rd Edition, Item 38: 通过 composition(复合)模拟 "has-a"(有一个)或 "is-implemented-in-terms-of"(是根据……实现的) | 旧一篇: [翻译] Effective C++, 3rd Edition, Item 36: 绝不要重定义一个 inherited non-virtual function(通过继承得到的非虚拟函数)

    Item 37: 绝不要重定义一个函数的 inherited default parameter value(通过继承得到的缺省参数值)

    作者:Scott Meyers

    译者:fatalerror99 (iTePub's Nirvana)

    发布:http://blog.csdn.net/fatalerror99/

    我们直接着手简化这个话题。只有两种函数能被你 inherit(继承):virtual(虚拟的)和 non-virtual(非虚拟的)。然而,重定义一个 inherited non-virtual function(通过继承得到的非虚拟函数)永远都是一个错误(参见 Item 36),所以我们可以安全地将我们的讨论限制在你继承了一个 virtual function with a default parameter value(带有一个缺省参数值的虚拟函数)的情形。

    在这种情况下,本 Item 的理由就变得非常地直截了当:virtual functions(虚拟函数)是 dynamically bound(动态绑定),而 default parameter values(缺省参数值)是 statically bound(静态绑定)。

    那又怎样呢?你说 static(静态)和 dynamic binding(动态绑定)之间的区别早已塞入你负担过重的头脑?(不要忘了,static binding(静态绑定)也以 early binding(前期绑定)闻名,而 dynamic binding(动态绑定)也以 late binding(后期绑定)闻名。)那么,我们就再来回顾一下。

    一个 object(对象)的 static type(静态类型)就是你在程序文本中声明给它的 type(类型)。考虑这个 class hierarchy(类继承体系):

    // a class for geometric shapes
    class Shape {
    public:
      enum ShapeColor { Red, Green, Blue };

      // all shapes must offer a function to draw themselves
      virtual void draw(ShapeColor color = Red) const = 0;
      ...
    };

    class Rectangle: public Shape {
    public:
      // notice the different default parameter value — bad!
      virtual void draw(ShapeColor color = Green) const;
      ...
    };

    class Circle: public Shape {
    public:
      virtual void draw(ShapeColor color) const;
      ...
    };

    直观地看,它看起来就像这个样子:

    现在考虑这些 pointers(指针):

    Shape *ps;                       // static type = Shape*
    Shape *pc = new Circle;          // static type = Shape*
    Shape *pr = new Rectangle;       // static type = Shape*

    在本例中,pspcpr 全被声明为 pointer-to-Shape 类型,所以它们全都以此作为它们的 static type(静态类型)。注意这就使得它们真正指向的东西完全没有区别——无论如何,它们的 static type(静态类型)都是 Shape*

    一个 object(对象)的 dynamic type(动态类型)取决于它当前引用的 object(对象)的 type(类型)。也就是说,它的 dynamic type(动态类型)表明它有怎样的行为。在上面的例子中,pc 的 dynamic type(动态类型)是 Circle*,而 pr 的 dynamic type(动态类型)是 Rectangle*。至于 ps,它没有一个实际的 dynamic type(动态类型),因为它(还)不能引用任何 object(对象)。

    dynamic types(动态类型),就像它的名字所暗示的,能在程序运行中变化,特别是通过 assignments(赋值):

    ps = pc;                       // ps's dynamic type is
                                   // now Circle*

    ps = pr;                       // ps's dynamic type is
                                   // now Rectangle*

    virtual functions(虚拟函数)是 dynamically bound(动态绑定),意味着被调用的特定函数取决于被用来调用它的那个 object(对象)的 dynamic type(动态类型):

    pc->draw(Shape::Red);             // calls Circle::draw(Shape::Red)

    pr->draw(Shape::Red);             // calls Rectangle::draw(Shape::Red)

    我知道,这全是老生常谈;你的确已经理解了 virtual functions(虚拟函数)。但是,当你考虑 virtual functions with default parameter values(带有缺省参数值的虚拟函数)时,就全乱了套,因为,如上所述,virtual functions(虚拟函数)是 dynamically bound(动态绑定),但 default parameters(缺省参数)是 statically bound(静态绑定)。这就意味着你最终调用了一个定义在 derived class(派生类)中的 virtual function(虚拟函数)却使用了一个来自 base class(基类)的 default parameter value(缺省参数值)。

    pr->draw();                       // calls Rectangle::draw(Shape::Red)!

    在此情况下,pr 的 dynamic type(动态类型)是 Rectangle*,所以正像你所希望的,Rectangle 的 virtual function(虚拟函数)被调用。在 Rectangle::draw 中,default parameter value(缺省参数值)是 Green。然而,因为 pr 的 static type(静态类型)是 Shape*,这个函数调用的 default parameter value(缺省参数值)是从 Shape class 中取得的,而不是 Rectangle class!导致的结果就是一个调用由“奇怪的和几乎完全出乎意料的 ShapeRectangle 两个 classes(类)中的 draw 声明的混合物”所组成。

    pspc,和 pr 是 pointers(指针)的事实与这个问题并无因果关系,如果它们是 references(引用),问题依然会存在。唯一重要的事情是 draw 是一个 virtual function(虚拟函数),而它的一个 default parameter values(缺省参数值)在一个 derived class(派生类)中被重定义。

    为什么 C++ 要坚持按照这种不正常的方式动作?答案是为了运行时效率。如果 default parameter values(缺省参数值)是 dynamically bound(动态绑定),compilers(编译器)就必须提供一种方法在运行时确定 virtual functions(虚拟函数)的 parameters(参数)的 default value(s)(缺省值),这比目前在编译期确定它们的机制更慢而且更复杂。最终的决定偏向了速度和实现的简单这一边,而造成的结果就是你现在可以享受高效运行的乐趣,但是,如果你忘记留心本 Item 的建议,就会陷入困惑。

    这样就很彻底而且完美了,但是看看如果你试图遵循本规则为 base(基类)和 derived classes(派生类)的用户提供同样的 default parameter values(缺省参数值)时会发生什么:

    class Shape {
    public:
      enum ShapeColor { Red, Green, Blue };

      virtual void draw(ShapeColor color = Red) const = 0;
      ...
    };

    class Rectangle: public Shape {
    public:
      virtual void draw(ShapeColor color = Red) const;
      ...
    };

    噢,code duplication(代码重复)。code duplication(代码重复)带来 dependencies(依赖关系):如果 Shape 中的 default parameter values(缺省参数值)发生变化,所有重复了它的 derived classes(派生类)必须同时变化。否则它们就陷入重定义一个 inherited default parameter value(通过继承得到的缺省参数值)。怎么办呢?

    当你要一个 virtual function(虚拟函数)按照你希望的方式运行有困难的时候,考虑可选的替代设计是很明智的,而且 Item 35 给出了多个 virtual function(虚拟函数)的替代方法。替代方法之一是 non-virtual interface idiom (NVI idiom)(非虚拟接口惯用法):用 base class(基类)中的 public non-virtual function(公有非虚拟函数)调用 derived classes(派生类)可能重定义的 private virtual function(私有虚拟函数)。这里,我们用 non-virtual function(非虚拟函数)指定 default parameter(缺省参数),同时使用 virtual function(虚拟函数)做实际的工作:

    class Shape {
    public:
      enum ShapeColor { Red, Green, Blue };

      void draw(ShapeColor color = Red) const           // now non-virtual
      {
        doDraw(color);                                  // calls a virtual
      }

      ...

    private:
      virtual void doDraw(ShapeColor color) const = 0;  // the actual work is
    };                                                  // done in this func

    class Rectangle: public Shape {
    public:

      ...

    private:
      virtual void doDraw(ShapeColor color) const;       // note lack of a
      ...                                                // default param val.
    };

    因为 non-virtual functions(非虚拟函数)绝不应该被 derived classes(派生类) overridden(覆盖)(参见 Item 36),这个设计使得 drawcolor parameter(参数)的 default value(缺省值)应该永远是 Red 变得明确。

    Things to Remember

    • 绝不要重定义一个 inherited default parameter value(通过继承得到的缺省参数值),因为 default parameter value(缺省参数值)是 statically bound(静态绑定),而 virtual functions ——应该是你可以 overriding(覆盖)的仅有的函数——是 dynamically bound(动态绑定)。

    发表于 @ 2005年11月15日 23:26:00|评论(loading...)|编辑

    新一篇: [翻译] Effective C++, 3rd Edition, Item 38: 通过 composition(复合)模拟 "has-a"(有一个)或 "is-implemented-in-terms-of"(是根据……实现的) | 旧一篇: [翻译] Effective C++, 3rd Edition, Item 36: 绝不要重定义一个 inherited non-virtual function(通过继承得到的非虚拟函数)

    评论

    #farproc 发表于2005-11-17 09:46:00  IP: 218.24.177.*
    Very Good!
    看了这篇文章,受益匪浅啊。想必以前的代码中有这样的错误,赶快回去改......

    感谢楼主
    #qxj 发表于2005-11-16 11:11:00  IP: 60.176.245.*
    继续加油,呵呵
    #fatalerror99 发表于2005-11-18 11:20:00  IP: 211.94.229.*
    to farproc
    辛辛苦苦搞出来的东西,如果能对别人有用,就是对我最大的鼓励了,谢谢 。
    #terence zhao 发表于2008-03-04 16:05:16  IP: 61.144.54.*
    感觉 读到现在,有时候感觉作者一直在作一个假设。然后我们在他们的假设中读书,不过思想还是不错的。
    发表评论  


    登录
    Csdn Blog version 3.1a
    Copyright © fatalerror99