本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie

关联条款 Item 36

接口继承和实现继承不同。在 public 继承下, derived classes 总是继承 base class 的接口

class Shape{
public:
virtual void draw() const = 0;
virtual void error(const std::string &msg);
int objectID() const;
//...
}; class Rectangle: public Shape{...};
class Ellipse: public Shape{...};

1.pure virtual 函数 --> 让 derived classes 仅仅继承函数接口。

Shape::draw 的声明式仍是对详细 derived classes 设计者说。 “你必须提供一个 draw 函数,但我不干涉你怎么实现它”



2.impure virtual 函数 --> 让 derived classes 继承该函数的接口和缺省实现

Shape::error 的声明式告诉 derived classes 设计者说, “你必须支持一个 error 函数,但假设你不想自己写一个,能够使用 Shape要提供的缺省版本号”



3.non-virtual 函数 --> 让 derived classes 继承函数的接口及一份强制性实现



class 设计常犯两个错误

1.将全部函数声明为 non-virtual

Item 7:为多态基类声明 virtual 析构函数

2.将全部成员函数声明为 virtual



经验: impure virtual 函数同一时候指定函数声明和函数缺省行为,可能造成危急。

演示样例:

class AirPort{...};
class AirPlane{
public:
virtual void fly(const AirPort &destination);
//...
};
void AirPort::fly(const AirPort &destination){
//缺省代码。将飞机飞至指定的目的地
}
class ModelA: public AirPlane {...};
class ModelB: public AirPlane {...}; class ModelC: public AirPlane {
... // 未声明 fly 函数, 但C型飞机的飞行方式与A。B不同。
}; AirPort PDX(...);
AirPlane *pa = new ModelC;
//...
pa->fly(PDX); //调用 AirPlane::fly

解析:

这个程序试图以 ModelA, ModelB 的飞行方式来飞 ModelC



纠正:

切断“virtual 函数接口” 和 其“缺省实现” 之间的连接。将 AirPlane::fly 改为一个 pure virtual 函数,仅仅提供飞行接口,

另以独立函数 defaultFly 提供缺省实现。

class AirPlane{
public:
virtual void fly(const AirPort &destination) = 0;
//...
protected: // protected 由于client不须要在意飞机能不能飞
void defaultFly(const AirPort &destination); //Item 36
}; void AirPlane::defaultFly(const AirPlane &destination){
//缺省代码,将飞机飞至指定的目的地
} class ModelA: public AirPlane{
public:
virtual void fly(const AirPort &destination){
defaultFly(destination);
}
//...
}; class ModelB: public AirPlane{
public:
virtual void fly(const AirPort &destination){
defaultFly(destination);
}
//...
}; class ModelC: public AirPlane{
public:
virtual void fly(const AirPort &destination);
//...
}; void ModelC::fly(const AirPort &destination){ // pure virtual 函数迫使 ModelC 必须提供自己的 fly 版本号
//...
}

纠正2:我更喜欢这个,没那么多变量名

class AirPlane{
public:
virtual void fly(const AirPort &destination) = 0;
//...
protected: // protected 由于client不须要在意飞机能不能飞
void defaultFly(const AirPort &destination); //Item 36
}; void AirPlane::fly(const AirPlane &destination){ //pure virtual 函数实现
//缺省代码。将飞机飞至指定的目的地
} class ModelA: public AirPlane{
public:
virtual void fly(const AirPort &destination){
AirPlane::fly(destination);
}
//...
}; class ModelB: public AirPlane{
public:
virtual void fly(const AirPort &destination){
AirPlane::fly(destination);
}
//...
}; class ModelC: public AirPlane{
public:
virtual void fly(const AirPort &destination);
//...
}; void ModelC::fly(const AirPort &destination){ // pure virtual 函数迫使 ModelC 必须提供自己的 fly 版本号
//...
}

Effective C++ Item 34 区分接口继承与实现继承的更多相关文章

  1. 读书笔记 effective c++ Item 34 区分接口继承和实现继承

    看上去最为简单的(public)继承的概念由两个单独部分组成:函数接口的继承和函数模板继承.这两种继承之间的区别同本书介绍部分讨论的函数声明和函数定义之间的区别完全对应. 1. 类函数的三种实现 作为 ...

  2. Effective C++ 34 区分接口继承和实现继承

    public继承从根本上讲,有两部分:接口继承和实现继承.两者之前的区别很像函数声明与函数定义. 具体设计中,会呈现三种形式:derived class只继承成员函数的接口(纯虚函数):derived ...

  3. 读书笔记 effective c++ Item 18 使接口容易被正确使用,不容易被误用

    1. 什么样的接口才是好的接口 C++中充斥着接口:函数接口,类接口,模板接口.每个接口都是客户同你的代码进行交互的一种方法.假设你正在面对的是一些“讲道理”的人员,这些客户尝试把工作做好,他们希望能 ...

  4. Effective C++ Item 36 绝不又一次定义继承而来的 non-virtual 函数

    本文为senlie原创.转载请保留此地址:http://blog.csdn.net/zhengsenlie 经验:绝对不要又一次定义继承而来的 non-virtual 函数 --> Item 7 ...

  5. Effective C++ Item 34 Differentiate between inheritance of interface and inheritance of implementation

    1. 成员函数的接口总是被继承. 如 Item32 所说, public 意味着 is-a, 所以对 base class 为真的任何事情对 derived class 也为真 2. 声明一个 pur ...

  6. Effective C++ Item 37 绝不又一次定义继承而来的缺省參数值

    本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 经验:绝对不要又一次而来的缺省參数值.由于缺省參数值都是静态绑定,而 virtual 函数 ...

  7. Effective JavaScript Item 34 在prototype上保存方法

    本系列作为EffectiveJavaScript的读书笔记. 不使用prototype进行JavaScript的编码是全然可行的,比如: function User(name, passwordHas ...

  8. Effective C++ -----条款34:区分接口继承和实现继承

    接口继承和实现继承不同.在public继承之下,derived classes总是继承base class的接口. pure virtual函数只具体指定接口继承. 简朴的(非纯)impure vir ...

  9. Effective C++:规定34:区分接口继承和实现继承

    (一个) class Shape { public: virtual void draw() const = 0; virtual void error(const string& msg); ...

随机推荐

  1. 关于引用iframe的一点小说明

    有时候,在web页面中使用iframe,可以解决一些实际问题,比如跨域访问等……这篇文章的关键不是iframe适用于哪些场景?而是iframe间如何进行互通?所谓互通是指: 情况1:在任何一个页面中调 ...

  2. Codeforces Round #445 C. Petya and Catacombs【思维/题意】

    C. Petya and Catacombs time limit per test 1 second memory limit per test 256 megabytes input standa ...

  3. Codeforces 813E Army Creation(主席树)

    题目链接  Educational Codeforces Round 22 Problem E 题意  给定一个序列,$q$次查询,询问从$l$到$r$中出现过的数字的出现次数和$k$取较小值后的和 ...

  4. [BZOJ 2547] 玩具兵

    Link: BZOJ 2547 传送门 Solution: 很容易通过解可行性的单调性想到二分答案,接下来考虑如何验证解 发现一个很奇妙的条件:步兵和骑兵的个数相同 因此交换位置时不用考虑可行性,保证 ...

  5. 3.1常用类(java学习笔记)包装类及日期类

    一.包装类 java是一门面向对象的语言,秉承一切皆对象的思想. 可java中有一些基本数据类型并不是对象,有时可能需要将它们变为对象. 这时就需要用到我们的包装类了. 基本数据类型 包装类 int ...

  6. linux 服务器信息查看

    写项目总结报告,需要统计需要系统的配合 1.# uname -a   (Linux查看版本当前操作系统内核信息) Linux localhost.localdomain 2.4.20-8 #1 Thu ...

  7. 队列 LinkedBlockingQueue

    1 api     java.util.concurrent包下的新类.LinkedBlockingQueue就是其中之一,是一个阻塞的线程安全的队列,底层采用链表实现.             Li ...

  8. C语言基础之函数

    1.什么情况下定义函数: 添加一个常用的新功能 2.函数的定义格式 返回值类型  函数名(形式参数列表) { 函数体 } 3.定义函数需要明确的东西 1> 起一个有意义的函数名 2> 函数 ...

  9. django 修改默认的user表和默认的认证系统

    django的功能非常强大,但是自带的user表很多情况下并不满足我们的需求,因此我们需要修改其默认的user表,并且把用username登录改成用email登录 第一步,创建自己的user表,在创建 ...

  10. @Component-@Resource-@Repository-@Service-@Controller的区别和理解-------springMVC

    1.作用: @Component------------------------泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注.(Component-------成分; 组分; 零件) ...