艺术编程

死不惊人死不休

翻译 [翻译] Effective C++, 3rd Edition, Item 32: 确保 public inheritance 模拟 "is-a"(上)收藏

Item 32: 确保 public inheritance 模拟 "is-a"

作者:Scott Meyers

译者:fatalerror99 (iTePub's Nirvana)

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

Some Must Watch While Some Must Sleep (W. H. Freeman and Company, 1974) 这本书中,William Dement 讲述了一个他试图让他的学生的记住他的课程中最重要的东西的故事。书中声称,他告诉他的班级,一般的英国中小学生对于 1066 年发生的 Hastings 战争的历史并没有什么了解。他着重强调,如果一个孩子记住了一点儿什么的,他或者她也就是记住了 1066 这个年代。对于上他的课程的学生,Dement 滔滔不绝地讲,其中只有很少的重要信息,包括安眠药却引起了失眠这样充满趣味的事情。他希望他的学生即使忘记课程中讨论的其它每一件事,也能记住这些很少的重大事件,而且他在整个学期再三地回顾这些基础的内容。

在课程结束的时候,期末考试的最后一道题是:“写下从这个课程中得到的,你一生都将确切地记住的一件事。”当 Dement 给这次考试打分的时候,他几乎晕了过去。几乎每一个人都写了"1066"。

因此,我一再煞费苦心地向你宣扬,使用 C++ 语言进行 object-oriented programming 时唯一最重要规则就是:public inheritance(公开继承)意味着 "is-a"。要让这个规则刻骨铭心。

如果你写了一个 class D ("Derived") 从 class B ("Base") 公开继承,你就是在告诉 C++ 编译器(以及你的代码的读者)每一个类型为 D 的对象也是一个类型为 B 的对象,但是反之则不然。你就是在说 B 描绘了一个比 D 更一般的概念,D 描述了一个比 B 更特殊的概念。你就是在声称一个类型为 B 的对象可以使用的任何地方,一个类型为 D 的对象一样可以使用,因为每一个类型为 D 的对象也就是一个类型为 B 的对象。另一方面,如果你需要一个类型为 D 的对象,一个类型为 B 的对象则不行:每一个 D 都是一个 B,但是反之则不然。

C++ 坚持对 public inheritance 的这一解释。考虑这个例子:

class Person {...};

class Student: public Person {...};

我们从日常的经验知道每一个学生都是一个人,但并不是每一个人都是一个学生。这就是由这个继承体系严格确定的意义。我们期望每一件对于人来说成立的事情——例如,他或她有一个出生日——对于一个学生来说也成立。我们不期望每一件对于学生来说成立的事情——例如,他或她在一所特定的学校注册——对于普通人来说也成立。一个人的概念比一个学生的概念更普通,一个学生一个专门类型的人。

在 C++ 领域中,任何期望引数类型为 Person(或 pointer-to-Person 或 reference-to-Person)的函数都可以接受一个 Student object(或 pointer-to-Student 或 reference-to-Student):

void eat(const Person& p);            // anyone can eat

void study(const Student& s);         // only students study

Person p;                             // p is a Person
Student s;                            // s is a Student

eat(p);                               // fine, p is a Person

eat(s);                               // fine, s is a Student,
                                      // and a Student is-a Person

study(s);                             // fine

study(p);                             // error! p isn't a Student

这一点只对 public inheritance 才成立。只有 Student 以 public 方式从 Person 派生,C++ 才有我所描述的行为。private inheritance 意味着完全不同的其它事情(参见 Item 39),而 protected inheritance 究竟意味什么使我困惑至今。

public inheritance 和 is-a 等价听起来简单,但有时你的直觉会误导你。例如,企鹅是一种鸟没有问题,而鸟能飞也没有问题。如果我们天真地试图用 C++ 来表达,我们就会得到:

class Bird {
public:
  virtual void fly();                  // birds can fly

  ...
};

class Penguin:public Bird {            // penguins are birds
  ...
};

突然间我们遇到了麻烦,因为这个继承体系表示企鹅能飞,我们知道这不是真的。发生了什么呢?

在这种情况下,我们成了不严谨的语言——英语的牺牲品。当我们说鸟能飞的时候,我们的意思并非是说所有种类的鸟都能飞,我们不过是说,大体上,鸟有飞的能力。如果我们说得更准确些,我们应该承认有几种不能飞的鸟,并提出如下继承体系,它对事实的模拟要好得多:

class Bird {
  ...                                       // no fly function is declared
};

class FlyingBird: public Bird {
public:
  virtual void fly();
  ...
};

class Penguin: public Bird {

  ...                                       // no fly function is declared

};

这个继承体系比最初的设计更忠实于我们真正知道的东西。

至此我们还是没有完全做好关于这些鸟的事情,因为对于某些软件系统来说,可能并不需要区分能飞的和不能飞的鸟。如果你的应用程序对于鸟喙和鸟翼做了很多处理,而不打算对飞行做什么处理的话,最初的 two-class 的继承体系可能完全适用。它是对“没有一个适用于所有软件的完美设计”这样的事实的一个简单反映。最好的设计依赖于系统究竟期望做什么,无论现在还是未来。如果你的程序对飞行一无所知,而且也不期望以后能知道些什么,那么不分辨能飞与不能飞的鸟可能就是一个非常完美的设计决策。事实上,它可能比区分它们的设计更为可取,因为你试图模拟的世界中就没有这样一种区分

对于如何处理我所说的“所有的鸟能飞,企鹅是鸟,企鹅不能飞,啊……哦……”的问题,还有另一种思想观念。那就是为企鹅重定义 fly 函数,以便让它产生一个运行时错误。

void error(const std::string& msg);       // defined elsewhere

class Penguin: public Bird {
public:
  virtual void fly() { error("Attempt to make a penguin fly!");}

  ...

};

认可“这里所说的一些事情与你所想的可能不同”是很重要的。这不是说“企鹅不能飞”。而是说“企鹅能飞,但对它试图真的这样做就是一个错误”。

(点击此处,接下篇)

发表于 @ 2005年09月09日 00:43:00|评论(loading...)

新一篇: [转载] 行走论坛,此帖独尊 | 旧一篇: [翻译] Effective C++, 3rd Edition, Chapter 6. Inheritance(继承)和 Object-Oriented Design(面向对象设计)

用户操作
[即时聊天] [发私信] [加为好友]
fatalerror
订阅我的博客
XML聚合  FeedSky
订阅到鲜果
订阅到Google
订阅到抓虾
fatalerror的公告
Copyleft © 2005 - 2009 by fatalerror99 (iTePub's Nirvana)

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

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

MSN: fatalerror9999@hotmail.com

e-mail: fatalerror99@gmail.com

文章分类
收藏
    My baby
    我家未未(RSS)
    Our Projects
    boost 文档汉化 boost_doc_translation(RSS)
    不服不行
    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
    C++ 的罗浮宫(RSS)
    Coofucoo's Blog--The Unadulterated Coofucoo(RSS)
    GreenCode's Blog(RSS)
    ilovevc 的专栏(RSS)
    Jeffrey Richter's Blog(RSS)
    lxwde 的专栏(RSS)
    oiramario(RSS)
    Ralph Zhang --- 在这里我只谈技术(RSS)
    ralph623 的专栏(RSS)
    renco 的专栏(RSS)
    Scorpio Auding @ Blog++(RSS)
    SnowFalcon 的专栏(RSS)
    Stan Lippman's BLog(RSS)
    Sutter's (Online) Mill(RSS)
    切尔斯基(RSS)
    刘未鹏 Mind Hacks
    周星星 之 Blog(RSS)
    孟岩(RSS)
    开心就好的代码人生(RSS)
    心如止水 —— coofucoo 的专栏(RSS)
    方舟(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
    NetBeans IDE
    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
    存档
    软件项目交易
    Csdn Blog version 3.1a
    Copyright © fatalerror