高效学 C++|继承与组合

news2024/12/22 22:48:44

继承是面向对象程序设计的重要特性之一。作为面向对象的编程语言,C++语言也自然支持这个特性。继承是代码复用的基本方法之一,也是接口和复用设计的关键。本文介绍继承的含义和继承与组合的关系。 

01、继承的含义

面向对象程序设计通过将问题域中的事物抽象成类来实现问题空间到程序空间的映射,从而简化问题的求解。然而,问题域中的事物并不处于同一个层次,往往可根据概念的抽象层次分为多层,比如汽车、火车、飞机等可抽象成更高层次的运输工具,而鸟、鱼、哺乳动物等可抽象成更高层次的动物。在抽象的不同层次中,抽象的高层具有的特征在抽象的低层都会体现,反之则不然。这个关系称之为继承关系。在继承关系中,称被继承的类为基类(或父类),称通过继承方式产生的新类为派生类(或子类、导出类)。例如运输工具可以作为基类,而汽车、火车和飞机则是从运输工具派生出的三个派生类,从它们还可以派生出许多的类。运输工具的部分层次结构如图1所示。

▋图1 运输工具的部分层次结构

通常,当一个类提供的功能不能满足新的要求,但该类提供的功能均可被重用且在概念上具有继承关系时,就会在该类的基础上使用继承机制从该类派生出新的类,并为新的类增加新的功能以满足要求。这样,不仅可以重复使用原有的、可靠的代码,减少工作量、增加工作效率,而且在程序的演化上也比较清楚,容易控制。

面向对象程序设计中的继承与现实中的继承有很大相关性,并且现实中的继承关系或逻辑系统中的继承关系可以帮助确定面向对象程序设计中的继承关系,但两者并不总是一致。例如,在逻辑上,圆是椭圆的一个特例,似乎椭圆是更高一层的抽象,然而在面向对象程序设计中,这是不合理的,因为椭圆中的长轴和短轴的概念对圆来说是没有意义的。总之,在面向对象程序设计中,需要合理使用继承关系,不能滥用。

组合也是一种代码重用的方法,它意味着组合类中的某些数据成员是其他已有类的对象。实际上,一直以来都在用组合的方式创建类,只不过是在用内部数据类型来组合新类。其实,使用用户自定义的类来组合新的类也很容易。

如果两个类间有继承关系,则意味着两个类间有“是一个”关系,并且较抽象的类的特性均适用于较一般的类。在实际使用中,到底选择继承还是组合,关键是分析类间的关系:如果类间有“是一个”关系,则需要考虑使用继承;如果有“整体-部分”(或“是...的一部分”)关系,则需要考虑使用组合。在此基础上还需要考虑基类的特性是否在派生类中均有意义。

02、继承与组合

通过继承可以节约编程量,例如在CBird类的print()函数的实现中,为了输出从基类继承下来的name和lifespan成员,仅需要调用基类的print()函数,这样既有很好的封装性,又节约了编程工作量。又如,在CBird类中,speak()函数可以直接从基类CAnimal继承,而不需要再次实现。

组合也是节约编程量的一种方法。那么什么时候使用继承、什么时候使用组合呢?这就需要考虑两个类之间的关系。当两个类间有“是一个”关系时,可以考虑使用继承,例如前面讲过的CBird类和CAnimal类;当两个类间有“有一个”关系,更准确地说有“是…的一部分”的关系时,需要考虑使用组合关系。

在实际使用中,组合关系常被误用为继承关系。为进一步明确组合与继承的不同,考虑下面这个情况:假设有一个圆类Circle,其有表示半径的数据成员,提供计算周长和面积的公有函数,并在此基础上设计圆柱体类Cylinder。类Circle的具体定义如下:

class Circle
{
public:
  Circle(double r = 0) : radius(r) { }
   double circumference() { return 2 * 3.14 * radius; }
   double area() { return 3.14 * radius * radius; }
   double get_radius() { return radius; }
private:
   double radius;
};

 如果现在要定义一个圆柱体Cylinder,则需要考虑圆柱体是在圆的基础上加上一个高构成,并且圆非圆柱,圆只是构成描述圆柱体的一部分而已,因此应使用组合来设计圆柱体类,具体定义如下:

class Cylinder
{
public:
   Cylinder(Circle c, double h) : btm(c), height(h) { }
   Circle bottom() { return btm; }
   double volume() { return btm.area() * height; }
private:
   Circle btm;
   double height;
};

当然,从功能上来说,可以通过继承来设计圆柱体类,即从Circle派生并添加一个高度成员,但这种设计思想是错误的,是对继承关系的滥用。示例程序如下:

class Cylinder : public Circle
{
public:
   Cylinder(double r, double h) : Circle(r), height(h) { }
   Circle bottom() { return *this; }
   double volume() { return this->area() * height; }
private:
   double height;
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/183483.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Web 应用程序的文件系统写入能力

介绍 NodeJS 之前&#xff0c;JS 操作文件只能通过 HTML <input type"file"> 元素或 XMLHttpRequest&#xff08;或之后的 fetch&#xff09;&#xff0c;来对本地文件进行一些浏览和上传操作。NodeJS 给予了 JS 操作系统底层 API 的能力&#xff0c;但这只能…

章节7 查看和处理文件内容

7-查看和处理文件内容 文本文件 ASCII、UTF-8、Unicode、ANSItxt、xml、conf、properties、yml等配置文件、日志文件、源代码 二进制文件 可执行文件、图片、音频、视频 cat 全拼&#xff1a;concatenate [kənˈkt(ə)nˌeɪt] 连接 格式&#xff1a;cat 文件名 more/…

eyeurl—一款网页批量截图工具

eyeurl使用说明 开发说明 eyeurl由作者&#xff1a;云小书 开发&#xff0c;源于日常渗透测试中&#xff0c;信息收集到的url过多&#xff0c;挨个打开查看比较繁琐&#xff0c;且效率极低&#xff0c;网上有大佬开发的eyewitness&#xff0c;且ui布局各方面都比较完善&#…

sadserver 题目思路概述

背景 从 阮一峰老师的博客 了解到 sadserver 可以在线挑战一些 linux 指令相关问题&#xff08;整体难度一般&#xff0c;但做题体验不错&#xff0c;有提示&#xff09;&#xff0c;这里将目前网站提供的的16道题进行简单解答&#xff0c;提供思路和相关指令 本文csdn 博客地…

初识Java虚拟机

1.概述 Java虚拟机&#xff1a;Java Virtual Machine。正是有了Java虚拟机&#xff0c;Java语言实现了跨平台的特性&#xff0c;一次编译&#xff0c;多处运行。 目前使用范围最广的虚拟机就是Hotspot VM&#xff0c;它是OracleJDK和OpenJDK中的默认Java虚拟机。 相比于其他…

[Android Studio]开发APP应用出现软件程序打开闪退的排错

&#x1f7e7;&#x1f7e8;&#x1f7e9;&#x1f7e6;&#x1f7ea; Android Debug&#x1f7e7;&#x1f7e8;&#x1f7e9;&#x1f7e6;&#x1f7ea; Topic 发布安卓学习过程中遇到问题解决过程&#xff0c;希望我的解决方案可以对小伙伴们有帮助。 &#x1f4cb;笔记目…

你还没用过Mybatis-Plus?丝般顺滑,快速上手!

一、概述 1.1、什么是MyBatis-Plus MyBatis-Plus (opens new window)&#xff08;简称 MP&#xff09;是一个 MyBatis (opens new window)的增强工具&#xff0c;在 MyBatis 的基础上只做增强不做改变&#xff0c;为简化开发、提高效率而生。 1.2、特性 无侵入&#xff1a;只做…

RabbitMQ入门前篇

本篇博文目录:一.RabbitMQ1.消息队列2.RabbitMQ3.安装RabbitMQ4.RabbitMQ常用命令二.使用RabbitMQ进行编程1.AMQP2.第一次MQ通信三.RabbitMQ六中工作模式1.RabbitMQ2.Work queues3.pub/sub订阅发布模式4.Routing模式5.主题Topic模式四.RabbitMQ消息确认机制五.源代码下载一.Rab…

我性格比较内向,适合做管理吗?

许多刚走上管理岗位的朋友&#xff0c;都有这样的困惑&#xff1a;1.我比较内向&#xff0c;不适合做管理。2.我不擅长演讲&#xff0c;没有领导才能。3.我太谨小慎微了&#xff0c;做不好领导。4.我太喜欢出风头&#xff0c;静不下心来做管理。5.我太强势了&#xff0c;团队很…

GuLi商城-项目初始结构创建,GitHub仓库创建

GitHub账号和密码 账号&#xff1a;11360XXXXXqq.com 密码&#xff1a;ZH**SH*19**1016 新建仓库&#xff1a; gulimall 记得勾选下Add a README file&#xff0c;上面忘记勾选了&#xff0c;实际建议还是要勾选下 复制路径&#xff1a; 打开IDEA检出项目 创建商品微服务模…

芯片设计|FPGA 设计的指导原则(一)

这一部分主要介绍 FPGA/CPLD 设计的指导性原则&#xff0c;如 FPGA 设计的基本原则、基本设计思想、基本操作技巧、常用模等。 FPGA/CPLD 设计的基本原则、思想、技巧和常用模块是一个非常大的问题&#xff0c;在此不可能面面俱到&#xff0c;只能我们公司项目中常用的一些设计…

权值线段树 详解+操作模板(c++)

文章目录权值线段树添加一个数字求某数出现的次数查询一段区间中数字出现的次数查询整个值域中第k小的数查询整个值域中第k大的数例子&#xff1a;求逆序对关于基本线段树与线段树的模板&#xff0c;请看我们之前发布的博客&#xff1a; 线段树入门详解 维护加法乘法&#xff0…

关于“茴香豆的‘茴’有几种写法”:学习过程中,若时间精力有限则优先记住最好用的一种

学习过程中的细节整理和精力节省权衡 我平时学习有整理总结、记笔记的习惯。 我学新东西总是很慢&#xff0c;因为细节处几乎都不会放过&#xff0c;会去发散&#xff0c;去深挖&#xff0c;去比较之前。 刚才上网&#xff0c;查了C语言中二维数组的赋值方式&#xff0c;某个…

UVM实战笔记(七)

第七章. UVM中的寄存器模型 7.1 寄存器模型简介 7.1.1 带寄存器配置总线的DUT 本章节使用的DUT带寄存器配置&#xff0c;代码如下&#xff1a; module dut(clk,rst_n,bus_cmd_valid,bus_op,bus_addr,bus_wr_data,bus_rd_data,rxd,rx_dv,txd,tx_en)input clk; …

DaVinci:Camera Raw(Sony RAW)

本文主要介绍 Sony RAW 格式素材相关的 Camera Raw 参数。解码质量Decode Quality解码质量决定了图像解拜耳之后所呈现的素质。默认为“使用项目设置” Use project setting&#xff0c;表示使用项目设置对话框中的“Camera RAW”解码质量设置。还可选择&#xff1a;全分辨率 -…

JavaEE-网络编程

目录一、网络编程套接字二、UDP Socket2.1 客户端服务器程序-回显服务(EchoServer)2.1.1 UdpEchoServer2.1.2 UdpEchoClient2.1.3 一个简单程序三、TCP 客户端服务器程序3.1 TCP API一、网络编程套接字 网络编程套接字就是操作系统给应用程序提供的一组API(叫做socket API)。 …

NLP学习笔记(七) BERT简明介绍

大家好&#xff0c;我是半虹&#xff0c;这篇文章来讲 BERT\text{BERT}BERT (Bidirectional Encoder Representations from Transformers) 原始论文请戳这里 0 概述 从某种程度上来说&#xff0c;深度学习至关重要的一环就是表征学习&#xff0c;也就是学习如何得到数据的向…

怎么把两个PDF合并?教你们几个简单的方法

不知道大家平时处理文件的数量多不多&#xff0c;但是小编日常处理文件真的特别多&#xff0c;所以小编经常会使用专业的格式转换器来处理文件&#xff0c;这样就可以高效处理文件了&#xff0c;例如我们需要将多个PDF文件合并&#xff0c;这样就只需要传输一个文件就可以了&am…

自定义starter解决请求绕过网关问题

引言 微服务项目中网关是一个常见的模块&#xff0c;通过网关的分发可以实现负载均衡、鉴权等操作&#xff1b;但是搭建好网关可以发现&#xff0c;虽然可以通过网关端口请求后端&#xff0c;如果有其他服务的地址依然可以使用其他服务地址绕过网关请求&#xff0c;这里我提供…

利用RadminLan和TcpRoute2将工作带回家

需要准备的工具 1.RadminLan 下载地址–>https://www.radmin-lan.cn/ 2.TcpRoute2 项目地址–>https://github.com/GameXG/TcpRoute2 *选用&#xff1a;浏览器插件proxy-switchyomega&#xff1a;https://microsoftedge.microsoft.com/addons/detail/proxy-switchyomega…