《Effective C++》学习笔记——区分接口继承和实现继承

2023-11-04

派生类public继承自基类,其中函数均是接口继承。

实现继承又分为缺省继承与强制继承,对应着虚函数与非虚函数。

我们在做项目时,对于任何事物都要抱有先描述再组织的心态。

因此,当描述事物为其构建框架尤其是存在继承(is-a)关系时,一定要搞清楚派生类与父类中函数关系。

基类函数类型 派生类继承方式
纯虚函数(pure virtual) 接口继承
普通虚函数(impure virtual) 接口继承+缺省实现继承
非虚函数(non-virtual) 接口继承+强制实现继承

实现基类函数时,我们需要考虑基类该函数与派生类该函数关系后,再给予具体的实现方式。

什么意思?

对于无需实例化的基类,完全可以将其声明为抽象类,其中声明的纯虚(pure virtual)函数可以只给出声明。

但如果所有派生类中该函数实现相同时,那可以将基类该函数声明为普通虚函数,这样当派生类定义时,可以直接调用基类函数,也就是缺省实现继承。

但这样也有可能引发意想不到的意外:

以书中例子做演示:

我们先定义一个基类飞机,它会实现一个飞行方法,因为所有的飞机都能飞。

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

之后派生出了各种不同型号的飞机...

class ModelA : public Airplane
{
	...//没有重定义fly,会缺省继承自基类Airplane
};
class ModelB : public Airplane
{
	...
};

两个派生类共用一个fly函数,因为它们性质相同(都能飞),即体现了相同特性还避免了代码复用,看起来很完美不是?

但此时如果需要新上线一款飞机,它与前两种的不同就在于飞行方式,又因为时间原因急于上架而忘记了对fly函数重定义,那灾难就发生了。

class ModelC : public Airplane
{
	... //未重定义fly函数
};

当我们调用ModelC的飞行方法时,它会按A和B的方式进行,这显然大错特错

ModelC c;
c.fly();//按A和B的方式飞行???

所以我们不妨将fly只提供一个接口给派生类,即只提供接口继承。这样当实现派生类时就会强迫它实现自己的fly版本。

class Airplane
{
public:
	virtual void fly() = 0;
};
class ModelC : public Airplane
{
public:
	void fly()//强迫实现,否则不能实例化
    {
        ...
    }
};

对于A和B而言,想体现相同特性又要避免重复,那么可以在基类中定义一个函数,供A和B显性调用即可

class Airplane
{
public:
	virtual void fly() = 0;
protected:
	void defaultFly()
	{
		...  //实现一个飞行方式 
	}
};
class ModelA : public Airplane
{
public:
	void fly() {  defaultFly();  }
    ...
};
class ModelB : public Airplane
{
public:
	void fly() {  defaultFly();  }
    ...
};

当然,这种方法也不是万全之策,因为它要求defaultFly函数应该是非虚(non-virtual)函数,任何一个派生类都不应该重定义它。

但假如一时糊涂不小心定义成了虚函数,那么对于像C那样的派生类就需要重定义defaultFly函数,但假如忘了呢?

对此我们可以有更好的方法:

将fly声明为纯虚函数并给出实现方法。派生类如果需要使用基类fly方法时可以通过作用域手动调用,也可以重写一份不一样的飞行方式。

class Airplane
{
public:
	virtual void fly() = 0
	{
		... //实现一份共同的飞行方式
	}
};
class ModelA : public Airplane
{
public:
	void fly()
	{  Airplane::fly();  }
};
class ModelB : public Airplane
{
public:
	void fly()
	{  Airplane::fly();  }
};
class ModelC : public Airplane
{
public:
	void fly()
	{
		... //重写一份不同的飞行方式
	}
};

go big or go home——facebook


如有错误,敬请斧正 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

《Effective C++》学习笔记——区分接口继承和实现继承 的相关文章

  • Effective C++

    条款01 视C 为一个语言联邦 将 视为一个由相关语言组成的联邦而非单一语言 条款02 尽量以const enum inline替换 define define处理与预处理阶段 而非编译阶段 因此此条款也可称为 宁可以编译器替换预处理器比较
  • Effective C++学习笔记——宁以传引用替换传值

    目录 一 传值效率可能会很低 二 传值可能发生割裂问题 三 适用于传值的情况和注意事项 相关博客 C 引用知识归纳 一 传值效率可能会很低 我们假设有这样两个类 class Human public string name string s
  • 编写new和delete时需固守常规——条款51

    条款50已解释什么时候你会想要写个自己的operator new和operator delete 但并没有解释当你那么做时必须遵守什么规则 这些规则不难奉行 但其中一些并不直观 所以知道它们究竟是些什么很重要 让我们从operator ne
  • 区分接口继承和实现继承——条款34

    表面上直截了当的public继承概念 经过严密的检查之后 发现它由两部分组成 函数接口 function interfaces 继承和函数实现 function implementations 继承 这两种继承的差异 很像本书导读所讨论的函
  • 透彻了解inlining的里里外外——条款30

    Inline函数 多棒的点子 它们看起来像函数 动作像函数 比宏好得多 见条款2 可以调用它们又不需要蒙受函数调用所招致的额外开销 你还能要求更多吗 你实际获得的比想到的还多 因为 免除函数调用成本 只是故事的一部分而已 编译器最优化机制通
  • 《Effective C++》学习笔记——区分接口继承和实现继承

    派生类public继承自基类 其中函数均是接口继承 实现继承又分为缺省继承与强制继承 对应着虚函数与非虚函数 我们在做项目时 对于任何事物都要抱有先描述再组织的心态 因此 当描述事物为其构建框架尤其是存在继承 is a 关系时 一定要搞清楚
  • 令operator=返回一个reference to *this——条款10

    关于赋值 有趣的是你可以把它们写成连锁形式 int x y z x y z 15 同样有趣的是 赋值采用右结合律 所以上述连锁赋值被解析为 x y z 15 这里15先被赋值给z 然后其结果 更新后的z 再被赋值给y 然后其结果 更新后的y
  • 尽可能延后变量定义式的出现时间——条款26

    只要你定义了一个变量而其类型带有一个构造函数或析构函数 那么当程序控制流 control flow 到达这个变量定义式时 你便得承受构造成本 当这个变量离开其作用域时 你便得承受析构成本 即使这个变量最终未被使用 仍需耗费这些成本 所以你应
  • 在operator=中处理“自我赋值”——条款11

    自我赋值 发生在对象被赋值给自己时 class Widget Widget w w w 赋值给自己 这看起来有点愚蠢 但它合法 所以不要认定客户绝不会那么做 此外赋值动作并不总是那么可被一眼辨识出来 例如 a i a j 潜在的自我赋值 如
  • 尽量以const、enum、inline替换 #define——条款02

    这个条款或许改为 宁可以编译器替换预处理器 比较好 因为或许 define 不能被视为语言的一部分 一 比如定义一个宏 define ASPECT RATIO 1 653 这个ASPECT RATIO也许从未被编译器看见 也许在编译器开始处
  • 将文件间的编译依存关系降至最低——条款31

    假设你对C 程序的某个class实现文件做了些轻微修改 注意 修改的不是class接口 而是实现 而且只改private成分 然后重新建置这个程序 并预计只花数秒就好 毕竟只有一个class被修改 你按下 Build 按钮或键入make 或
  • 条款13: 以对象管理资源

    结论 为防止资源泄漏 请使用RAII对象 它们在构造函数中获得资源并在析构函数中释放资源 两个常被使用的RAII classes分别是tr1 share ptr和auto ptr 前者通常是较佳选择 因为其copy行为比较直观 若选择aut
  • Effective C++改善程序与设计的55个具体做法笔记

    Scott Meyers大师Effective三部曲 Effective C More Effective C Effective STL 这三本书出版已很多年 后来又出版了Effective Modern C More Effective
  • 《Effective C++》 全书内容提炼总结

    个人博客地址 https cxx001 gitee io 本文阅读说明 孔子云 取乎其上 得乎其中 取乎其中 得乎其下 取乎其下 则无所得矣 对于读书求知而言 这句古训教我们去读好书 最好是好书中的上品 经典书 Effective C 就是
  • C++ Primer笔记——tuple类型

    tuple类型 C Primer 17 1 tuple类型 P636 tuple是一种定义在标准库中的类似于pair的模板 pair的成员为两个不同的类型 tuple同样要求成员类型不同 但是tuple可以有任意数量的成员 一 定义 定义一
  • Effective C++ 条款十二:复制对象时勿忘其每一个成分

    这句话包含两部分的意思 第一部分是要考虑到所有成员变量 特别是后加入的 相应的拷贝构造函数和赋值运算符要及时更新 第二部分是在存在继承时 不要遗忘基类部分的复制 先看第一部分的意思 举个例子 class SampleClass privat
  • Effective C++ 学习笔记 《六》

    Item 6 Explicitly disallow the use of compiler generated functions you do not want 其实这一节的内容是和item5紧密相连的 上一节的核心围绕着编译器会自动生
  • 将与参数无关的代码抽离templates——条款44

    Templates是节省时间和避免代码重复的一个奇方妙法 不再需要键入20个类似的classes而每一个带有15个成员函数 你只需键入一个class template 留给编译器去具现化那20个你需要的相关classes和300个函数 cl
  • 考虑virtual函数以外的其他选择——条款35

    假设你正在写一个视频游戏软件 你打算为游戏内的人物设计一个继承体系 你的游戏术语暴力砍杀类型 剧中人物被伤害或因其他因素而降低健康状态的情况并不罕见 你因此决定提供一个成员函数healthValue 它会返回一个整数 表示人物的健康程度 由
  • 复制对象时勿忘其每一个成分——条款12

    设计良好之面向对象系统 OO systems 会将对象的内部封装起来 只留两个函数负责对象拷贝 复制 那便是带着适切名称的copy构造函数和copy assignment操作符 我称它们为copying函数 条款5观察到编译器会在必要的时候

随机推荐

  • 方法注入以及bean的作用域

    方法注入 Spring在初始化容器的时候对配置
  • Dos启动远程桌面命令

    打开 Remote Registry Service这个服务 用mstsc命令运行 远程管理软件集合介绍 http bbs kafan cn thread 218201 1 1 html
  • Python将COCO格式实例分割数据集转换为YOLO格式实例分割数据集

    Python将COCO格式实例分割数据集转换为YOLO格式实例分割数据集 前言 相关介绍 COCO格式实例分割数据集转换为YOLO格式实例分割数据集 coco格式对应的json文件 以test json为例 格式转换代码 内容如下 前言 由
  • c++STL容器的通用接口(c++STL相关)

    STL容器具有以下一些特点 1 STL主要通过模板方式进行接口编程 2 用了move后原来的左值引用就不存在了 3 对于所有container有begin和end和empty 大多数都有size 除了forward list 大多数都有cl
  • c++primer exercises 7.0

    Exercise 7 1 What is th difference betwen a parameter and an argument Ans 形参与实参的区别 1 初始化方式 形参在函数的形参表里定义 由函数调用的时候 实参来初始化
  • 阿里巴巴Java开发手册代码规范

    阿里巴巴Java开发手册代码规范 转载自 阿里巴巴Java开发规约插件p3c详细教程及使用感受 如有侵权 请联系我删除 开源地址 https github com alibaba p3c tree master idea plugin 使用
  • 毕业设计 基于单片机的数字出租车计价器

    0 前言 这两年开始毕业设计和毕业答辩的要求和难度不断提升 传统的毕设题目缺少创新和亮点 往往达不到毕业答辩的要求 这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求 为了大家能够顺利以及最少的精力通过毕设 学长分享优质毕业设计项
  • 在ubuntu环境下安装python3虚拟环境

    目的 为了各个python项目间的模块包版本不互相影响 创建虚拟环境 针对某一项目使用对应的虚拟环境 这样当其他项目使用更高版本模块包的时候 也不会影响此项目中的包的使用 环境 Linux操作系统 ubuntu18 10 python版本
  • 【Unity编程】欧拉角与万向节死锁(图文版)

    万向节死锁 Gimbal Lock 问题 上文中曾经说过 欧拉旋转的顺规和轴向定义 自然造就了 万向节死锁 问题 本文主要来探索它自然形成的原因 陀螺仪 首先 我们来了解Gimbal 究竟是个什么玩意儿 下面来自维基百科中关于Gimbal的
  • 海南省工业学校计算机,直播预告丨特色职教育英才!7日下午邀你“云”探访海南省工业学校...

    新海南客户端 南海网 南国都市报7月6日消息 记者 杜倬荷 你想知道电工电子与自动化实训基地究竟长什么样吗 汽车运用与维修实训都有哪些内容 由新海南客户端 南海网 南国都市报联合推出的 建设自贸港 我们一起来 海南中职院校直播探校系列活动
  • [源码和文档分享]Python实现基于AdaBoost算法的微博情感分类系统

    摘 要 随着互联网的快速发展 各类社交媒体平台如微信 QQ等也与日俱增 而微博更是集成了传统网站 论坛 博客等的优点 并加上了人与人之间的互动性 关系亲密程度等多种智能算法 并以简练的形式让数据爆发性的传播 促进了人与人之间的交流 网民可以
  • for循环作用域问题(var和let)

    看这个 var arr for var i 0 i lt 10 i arr i function console log i arr 0 10 arr 1 10 arr 2 10 arr 3 10 还有这个 ul li 1 li li 2
  • 华为服务器格式化系统,服务器操作系统格式化

    服务器操作系统格式化 内容精选 换一换 本文以云服务器的操作系统为 Windows Server 2008 R2 Standard 64bit 磁盘容量为3 TB举例 提供容量大于2 TB的Windows数据盘的初始化操作指导 MBR格式分
  • Microsoft 365的密钥

    Microsoft 365 的密钥是一个字符串 用于激活 Microsoft 365 订阅 它是唯一的 并且需要在订阅期间进行激活 以便可以使用所订阅的服务 如果您没有密钥 或者密钥无效 您将无法使用 Microsoft 365 服务
  • 高并发之API接口限流

    在开发高并发系统时有三把利器用来保护系统 缓存 降级和限流 缓存 缓存的目的是提升系统访问速度和增大系统处理容量 降级 降级是当服务出现问题或者影响到核心流程时 需要暂时屏蔽掉 待高峰或者问题解决后再打开 限流 限流的目的是通过对并发访问
  • cadence allegro 封装焊盘编号修改 (引脚编号修改)

    1 打开dra文件在find里面 off all 然后只点击text 2 点击需要更改的焊盘 3 菜单栏edit text 4 弹出窗口修改即可 注意 按照网上的其他操作并没有执行步骤1操作 我尝试过不好使 由于项目需要应用多年的AD软件转
  • 【面试】linux && gdb

    Linux Linux开发你们怎么上传文件的 gdb linux断点所有线程都会停住吗 GDB查看所有线程栈命令 当程序在gdb下因任何原因停止时 例如达到断点 所有执行线程都将停止 而不仅仅是当前线程 Linux上传文件的方法 mac s
  • C# NPOI 创建Excel

    C NPOI 创建Excel NPOI是一个供给C 操作导入或导出Excel的开源工具 NET版本 NET 5 NPOI版本 2 6 0 基本使用思路 创建工作薄 Workbook 工作薄 Workbook 中创建工作表 WorkSheet
  • MySQL 深度分页性能急剧下降,该如何优化?

    1 背景 mysql使用select limit offset rows分页在深度分页的情况下 性能急剧下降 例如 select 的情况下直接 limit 600000 10 扫描的是约60万条数据 并且是需要回表60W次 也就是说 部分性
  • 《Effective C++》学习笔记——区分接口继承和实现继承

    派生类public继承自基类 其中函数均是接口继承 实现继承又分为缺省继承与强制继承 对应着虚函数与非虚函数 我们在做项目时 对于任何事物都要抱有先描述再组织的心态 因此 当描述事物为其构建框架尤其是存在继承 is a 关系时 一定要搞清楚