当前位置: 首页 > news >正文

每日一问:C++ 如何实现继承、封装和多态

每日一问:C++ 如何实现继承、封装和多态

C++ 是一门面向对象编程语言,通过继承、封装和多态这三个核心特性实现了对复杂系统的高效管理和扩展。继承让代码重用性得以提升,封装保护数据的完整性,而多态通过不同的接口实现了灵活性。本文将详细讲解 C++ 如何实现继承、封装和多态,探讨各自的实现机制及实际应用。


文章目录

  • 每日一问:C++ 如何实现继承、封装和多态
    • 摘要
    • 一、继承:实现代码复用
      • 1.1 继承的基本概念
      • 1.2 继承的实现方式
      • 1.3 多重继承与虚基类
    • 二、封装:保护数据的完整性
      • 2.1 封装的基本概念
      • 2.2 封装的实现方式
      • 2.3 组合与聚合
    • 三、多态:提升系统的灵活性
      • 3.1 多态的基本概念
      • 3.2 多态的实现方式
      • 3.3 动态绑定与静态绑定
      • 3.4 多态的应用场景
    • 四、总结

摘要

本文探讨了 C++ 中实现继承、封装和多态的方式,包括类的定义与成员函数、访问权限控制、虚函数与纯虚函数、函数重载与重写等。通过代码示例,详细讲解了这些概念在 C++ 中的实际应用,帮助读者理解面向对象编程的精髓。

一、继承:实现代码复用

1.1 继承的基本概念

继承是 C++ 提供的代码复用机制,通过继承,派生类(Derived Class)可以直接继承基类(Base Class)的属性和方法,从而避免重复代码。继承的关键在于扩展现有类的功能,同时保持逻辑的一致性。

1.2 继承的实现方式

  • 基类与派生类:通过定义一个基类,然后让其他类继承该基类,从而复用基类中的代码。
  • 访问权限控制:继承中可以通过 publicprotectedprivate 控制派生类对基类成员的访问权限。

示例代码

#include <iostream>
using namespace std;// 定义一个基类 Animal
class Animal {
public:void eat() {  // 基类的成员函数cout << "Eating..." << endl;}
};// 定义一个派生类 Dog,继承自 Animal
class Dog : public Animal {
public:void bark() {  // 派生类的成员函数cout << "Barking..." << endl;}
};int main() {Dog dog;  // 创建派生类对象dog.eat();  // 调用继承自基类的函数dog.bark();  // 调用派生类自己的函数return 0;
}

解释:在这个示例中,Dog 类继承了 Animal 类,得以直接使用基类的 eat() 方法,同时扩展了自己的 bark() 方法。

1.3 多重继承与虚基类

C++ 支持多重继承,即一个类可以同时继承多个基类。但这也可能带来“菱形继承”问题,为此引入了虚基类(Virtual Base Class)解决重复继承的问题。

示例代码

#include <iostream>
using namespace std;// 定义虚基类 A
class A {
public:void show() {cout << "Class A" << endl;}
};// 定义 B 和 C 类,虚继承自 A
class B : virtual public A {};
class C : virtual public A {};// 定义 D 类,继承自 B 和 C
class D : public B, public C {};int main() {D d;  // 创建 D 类对象d.show();  // 调用 show 函数,避免菱形继承问题return 0;
}

解释:虚基类通过消除重复继承的问题,确保了 A 类只会被继承一次,从而避免数据冗余。

二、封装:保护数据的完整性

2.1 封装的基本概念

封装是将数据和操作封装在一个类中,通过访问控制保护数据不被非法访问。C++ 通过访问控制符 publicprotectedprivate 实现封装,确保对象的内部状态只能通过合法的方式改变。

2.2 封装的实现方式

  • 访问控制public 用于对外开放的成员,protected 对继承的派生类开放,private 对类外部完全隐藏。
  • 构造函数与析构函数:通过构造函数和析构函数控制对象的初始化和销毁,确保对象在合适的状态下创建和销毁。

示例代码

#include <iostream>
using namespace std;// 定义类 Box,演示封装
class Box {
private:double length;  // 私有成员变量double width;   // 私有成员变量public:// 构造函数Box(double l, double w) : length(l), width(w) {}// 公有成员函数,获取面积double getArea() {return length * width;}
};int main() {Box box(5.0, 3.0);  // 创建 Box 对象cout << "Area: " << box.getArea() << endl;  // 访问公有成员函数return 0;
}

解释Box 类通过封装,将 lengthwidth 设置为私有,仅通过公有函数 getArea() 对外暴露,这种封装方式保护了数据的完整性。

2.3 组合与聚合

组合和聚合是将类组合起来形成复杂对象的方式。组合是强关联,表示成员对象的生命周期与类对象绑定;聚合是弱关联,成员对象的生命周期独立于类对象。

示例代码

#include <iostream>
#include <string>
using namespace std;class Engine {
public:void start() {cout << "Engine started." << endl;}
};// Car 类组合了 Engine 类
class Car {
private:Engine engine;  // 组合关系,Car 拥有 Enginepublic:void start() {engine.start();  // 使用 Engine 对象的成员函数cout << "Car started." << endl;}
};int main() {Car car;  // 创建 Car 对象car.start();  // 调用 Car 对象的 start 函数return 0;
}

解释:在这个示例中,Car 类组合了 Engine 类,通过 engine 对象调用 start() 方法,展示了组合关系。

三、多态:提升系统的灵活性

3.1 多态的基本概念

多态是指同一接口可以有不同实现的能力,它是面向对象编程的核心。C++ 通过函数重载、运算符重载、虚函数和纯虚函数实现多态。多态可以分为静态多态和动态多态

3.2 多态的实现方式

  • 重载:在同一作用域中定义多个同名但参数不同的函数,属于静态多态(编译时多态)。
  • 重写:派生类重新定义基类中的虚函数,实现动态多态(运行时多态)。
  • 虚函数与纯虚函数:通过虚函数实现动态绑定,通过纯虚函数定义接口,强制派生类实现接口方法。

示例代码

#include <iostream>
using namespace std;// 基类 Shape,定义纯虚函数
class Shape {
public:virtual void draw() = 0;  // 纯虚函数,定义接口
};// 派生类 Circle,重写基类的 draw 函数
class Circle : public Shape {
public:void draw() override {  // 重写 draw 函数cout << "Drawing a circle." << endl;}
};// 派生类 Rectangle,重写基类的 draw 函数
class Rectangle : public Shape {
public:void draw() override {  // 重写 draw 函数cout << "Drawing a rectangle." << endl;}
};int main() {Shape* shape1 = new Circle();  // 创建 Circle 对象Shape* shape2 = new Rectangle();  // 创建 Rectangle 对象shape1->draw();  // 调用 Circle 的 draw 函数shape2->draw();  // 调用 Rectangle 的 draw 函数delete shape1;  // 释放对象内存delete shape2;  // 释放对象内存return 0;
}

解释:在这个示例中,Shape 类定义了一个纯虚函数 draw()CircleRectangle 分别重写该函数,实现了动态多态。

3.3 动态绑定与静态绑定

静态绑定是在编译时确定调用的函数(如重载),而动态绑定是在运行时根据对象类型确定调用的函数(如重写)。

3.4 多态的应用场景

多态在设计模式中的应用广泛,如工厂模式和策略模式。工厂模式通过返回基类指针,实现对象的创建与替换;

策略模式允许在运行时选择具体实现。

示例代码

#include <iostream>
#include <memory>
using namespace std;// 定义抽象基类 PaymentStrategy
class PaymentStrategy {
public:virtual void pay() = 0;  // 纯虚函数,定义支付方法接口
};// 定义具体策略类 CreditCardPayment
class CreditCardPayment : public PaymentStrategy {
public:void pay() override {cout << "Paying with Credit Card." << endl;}
};// 定义具体策略类 PayPalPayment
class PayPalPayment : public PaymentStrategy {
public:void pay() override {cout << "Paying with PayPal." << endl;}
};// 购物车类,使用策略模式
class ShoppingCart {
private:PaymentStrategy* strategy;  // 策略模式中的支付策略public:ShoppingCart(PaymentStrategy* s) : strategy(s) {}void checkout() {strategy->pay();  // 执行具体支付策略}
};int main() {PaymentStrategy* pay1 = new CreditCardPayment();PaymentStrategy* pay2 = new PayPalPayment();ShoppingCart cart1(pay1);  // 使用信用卡支付策略ShoppingCart cart2(pay2);  // 使用 PayPal 支付策略cart1.checkout();  // 调用信用卡支付cart2.checkout();  // 调用 PayPal 支付delete pay1;delete pay2;return 0;
}

解释:在上述代码中,通过策略模式实现了动态选择不同支付方式的功能,这展示了多态在实际应用中的灵活性和扩展性。

四、总结

继承、封装和多态是 C++ 面向对象编程的核心。通过继承实现代码复用,通过封装保护数据完整性,通过多态提升系统灵活性。理解这些机制不仅能提升编程能力,还能设计出高效、灵活且可维护的系统。

特性实现方式关键机制
继承基类与派生类、多重继承与虚基类代码复用、继承关系、消除重复继承问题
封装访问控制、构造与析构函数、组合与聚合保护数据完整性、控制对象生命周期
多态函数重载、重写、虚函数与纯虚函数静态绑定、动态绑定、灵活接口实现

通过这些特性,C++ 程序能够更好地管理复杂性,提高代码的复用性和可维护性。在实际编程中,根据需求选择合适的机制,能有效提升软件开发的质量和效率。

相关文章:

每日一问:C++ 如何实现继承、封装和多态

每日一问&#xff1a;C 如何实现继承、封装和多态 C 是一门面向对象编程语言&#xff0c;通过继承、封装和多态这三个核心特性实现了对复杂系统的高效管理和扩展。继承让代码重用性得以提升&#xff0c;封装保护数据的完整性&#xff0c;而多态通过不同的接口实现了灵活性。本文…...

STM32常用数据采集滤波算法

例如&#xff0c;STM32进行滤波处理时&#xff0c;主要目的是处理数据采集过程中可能产生的噪声和尖刺信号。这些噪声可能来自电源干扰、传感器自身的不稳定性或其他外部因素。 1.一阶互补滤波 方法&#xff1a;取a0~1,本次滤波结果&#xff08;1-a&#xff09;本次采样值a上…...

二分系列(二分查找)9/12

一、分情况讨论 1.左闭右闭:[left,right] 因为是左闭右闭&#xff0c;所以left和right都能直接取到。 #这里将>放到一起&#xff0c;当nums[mid]>target的时候&#xff0c; 要更新右边界&#xff0c;rightmid-1,这样就把一些相同的情况也切出去了 可以理解为找的第一个…...

如何通过可视化大屏,助力智慧城市的“城市微脑”建设?

在智慧城市的宏伟蓝图中&#xff0c;常常面临着一个关键挑战&#xff1a;如何确保这些理念和技术能够真正地惠及城市的每一个角落&#xff0c;每一个产业&#xff0c;以及每一位市民。问题的核心在于城市的具体应用场景&#xff0c;无论是横向的社区、园区、镇街、学校、酒店、…...

何时空仓库

某仓库现存货物 s 箱&#xff0c;每天上午出货 m 箱、下午进货 n 箱&#xff0c;若s≥m>n≥0&#xff0c;则第 k 天将会出现空仓的情况。请你帮仓库管理员编写程序&#xff0c;输入s、m 和 n&#xff0c;计算并输出 k。 输入格式 s,m,n (s≥m>n≥0) 输出格式 k 输入样例…...

美创获评CNVD年度原创漏洞发现贡献单位!

9月10日&#xff0c;第21届中国网络安全年会暨网络安全协同治理分论坛在广州成功举办。会上&#xff0c;美创科技首次获评“CNVD年度原创漏洞发现贡献单位”。 美创科技依托第59号安全实验室&#xff0c;专注数据安全技术和攻防研究。凭借深厚的技术积累与优势&#xff0c;被遴…...

Spring 循环依赖原理及解决方案

一、什么是循环依赖 循环依赖指的是一个实例或多个实例存在相互依赖的关系&#xff08;类之间循环嵌套引用&#xff09;。 举例&#xff1a; Component public class AService {// A中注入了BAutowiredprivate BService bService; }Component public class BService {// B中也…...

【数据结构与算法 | 灵神题单 | 插入链表篇】力扣2807, LCR 029, 147

1. 力扣2807&#xff1a;在链表中插入最大公约数 1.1 题目&#xff1a; 你一个链表的头 head &#xff0c;每个结点包含一个整数值。 在相邻结点之间&#xff0c;请你插入一个新的结点&#xff0c;结点值为这两个相邻结点值的 最大公约数 。 请你返回插入之后的链表。 两个…...

瑞芯微rv1126 Linux 系统,修改系统时区,包有效方法

在 Linux 系统中,修改时区的步骤通常包括创建符号链接到正确的时区文件,并确保相关的配置文件已正确更新。然而,某些系统可能有额外的步骤或需要修改其他配置文件来使更改生效。以下是一些步骤。 1. 创建符号链接 ln -sf /usr/share/zoneinfo/Asia/Hong_Kong /etc/localti…...

系统架构设计师:数据库设计

简简单单 Online zuozuo: 简简单单 Online zuozuo 简简单单 Online zuozuo 简简单单 Online zuozuo 简简单单 Online zuozuo :本心、输入输出、结果 简简单单 Online zuozuo : 文章目录 系统架构设计师:数据库设计前言数据库基础概念数据模型三要素数据库的三级模型和两级…...

代码随想录刷题day31丨56. 合并区间,738.单调递增的数字,总结

代码随想录刷题day31丨56. 合并区间&#xff0c;738.单调递增的数字&#xff0c;总结 1.题目 1.1合并区间 题目链接&#xff1a;56. 合并区间 - 力扣&#xff08;LeetCode&#xff09; 视频讲解&#xff1a;贪心算法&#xff0c;合并区间有细节&#xff01;LeetCode&#x…...

深圳建站公司-如何做网站

深圳建站公司&#xff1a;如何制作一个成功的网站 在信息化快速发展的今天&#xff0c;企业和个人越来越重视网络形象&#xff0c;网站成为了展示品牌、推广产品和服务的重要平台。深圳作为科技创新和经济发展的前沿城市&#xff0c;涌现出许多专业的建站公司&#xff0c;能够为…...

Google Earth Engine(GEE)——随时间推移的降雨趋势案例分析(大规模气候监测)

简介 探索 Google Earth Engine环境类型中不同的数据。到目前为止,我们主要使用光学卫星数据,并探索了植被随时间和空间的趋势。然而,仅仅跟踪植被特性的变化并不足以了解是什么驱动了它们——我们需要能够将这些动态与其他环境数据联系起来。 在交互式 GEE 控制台中为您感…...

从新手到高手:用这9个策略让ChatGPT成为你的私人顾问!

ChatGPT已经出来快一年多了&#xff0c;但是我发现周围的小伙伴还是处在调戏ChatGPT的阶段&#xff0c;并没有在日常工作和生活中发挥他应由的价值。我调研下来发现最关键的痛点就是&#xff1a;不知道该怎么写Prompt可以让ChatGPT输出期望的回答。 哎吆&#xff0c;这不正是撞…...

高精度定位系统中的关键技术:GGA、EHP、RTMC、IMU、GNSS、INS 和 RTK 的协同工作

文章目录 0. 概述1. GGA&#xff1a;标准的定位数据格式2. EHP&#xff1a;增强高度精度3. RTMC&#xff1a;实时监控与控制4. IMU 和 INS&#xff1a;惯性测量和导航系统5. GNSS&#xff1a;全球导航卫星系统6. RTK&#xff1a;实时动态差分定位7. 各技术的融合与协同GPS 数据…...

Spring3~~~

目录 多例 后置处理器BeanPostProcessor XML配置 通过注解 AOP与后置处理器 JdbcTemplate jdbc.properties jdbc.xml Test 具名参数 DAO 声明式事务 GoodsDao GoodsService xml 传播机制 种类 隔离级别 超时回滚 如果是普通的java项目&#xff0c;xml文件放…...

微服务CI/CD实践(五)Jenkins Docker 自动化构建部署Java微服务

微服务CI/CD实践系列&#xff1a; 微服务CI/CD实践&#xff08;一&#xff09;环境准备及虚拟机创建 微服务CI/CD实践&#xff08;二&#xff09;服务器先决准备 微服务CI/CD实践&#xff08;三&#xff09;Jenkins部署及环境配置 微服务CI/CD实践&#xff08;四&#xff09;…...

泰州高新区法院多层面强化固定资产管理

固定资产管理是法院的一项基础性工作&#xff0c;法院经费支出相当一部分用于固定资产的购置&#xff0c;为了提高固定资产使用质效&#xff0c;为执法办案提供坚实的保障&#xff0c;高新区法院积极探索科学合理的固定资产管理策略&#xff0c;更新管理思想&#xff0c;完善管…...

JDBC简介与应用:Java数据库连接的核心概念和技术

简短介绍 JDBC 及其重要性。 简短介绍 JDBC JDBC&#xff08;Java Database Connectivity&#xff09;是一种用于执行 SQL 语句的 Java API 并且独立于特定的数据库厂商。它允许开发者以一种标准的方式从 Java 应用程序中访问关系型数据库&#xff0c;这意味着一旦你掌握了 J…...

倒反天罡!这个AI风格模型可自由训练,还能批量生成同风格图像

在AIGC的新纪元中&#xff0c;模型已晋升为与算力并驾齐驱的生产力核心要素。也有不少用户反馈提到&#xff0c;如何利用神采PromeAI训练属于自己的风格模型&#xff1f;这需求必须安排&#xff01;神采PromeAI「一致性模型」正式上线&#xff01; 可自主训练风格化模型&#x…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统&#xff0c;智慧工地全套源码&#xff0c;java版智慧工地源码&#xff0c;支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求&#xff0c;提供“平台网络终端”的整体解决方案&#xff0c;提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

Docker 运行 Kafka 带 SASL 认证教程

Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明&#xff1a;server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI

前一阵子在百度 AI 开发者大会上&#xff0c;看到基于小智 AI DIY 玩具的演示&#xff0c;感觉有点意思&#xff0c;想着自己也来试试。 如果只是想烧录现成的固件&#xff0c;乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外&#xff0c;还提供了基于网页版的 ESP LA…...

unix/linux,sudo,其发展历程详细时间线、由来、历史背景

sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)

本文把滑坡位移序列拆开、筛优质因子&#xff0c;再用 CNN-BiLSTM-Attention 来动态预测每个子序列&#xff0c;最后重构出总位移&#xff0c;预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵&#xff08;S…...

基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解

JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用&#xff0c;结合SQLite数据库实现联系人管理功能&#xff0c;并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能&#xff0c;同时可以最小化到系统…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题

分区配置 (ptab.json) img 属性介绍&#xff1a; img 属性指定分区存放的 image 名称&#xff0c;指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件&#xff0c;则以 proj_name:binary_name 格式指定文件名&#xff0c; proj_name 为工程 名&…...

【分享】推荐一些办公小工具

1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由&#xff1a;大部分的转换软件需要收费&#xff0c;要么功能不齐全&#xff0c;而开会员又用不了几次浪费钱&#xff0c;借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...

宇树科技,改名了!

提到国内具身智能和机器人领域的代表企业&#xff0c;那宇树科技&#xff08;Unitree&#xff09;必须名列其榜。 最近&#xff0c;宇树科技的一项新变动消息在业界引发了不少关注和讨论&#xff0c;即&#xff1a; 宇树向其合作伙伴发布了一封公司名称变更函称&#xff0c;因…...

STM32---外部32.768K晶振(LSE)无法起振问题

晶振是否起振主要就检查两个1、晶振与MCU是否兼容&#xff1b;2、晶振的负载电容是否匹配 目录 一、判断晶振与MCU是否兼容 二、判断负载电容是否匹配 1. 晶振负载电容&#xff08;CL&#xff09;与匹配电容&#xff08;CL1、CL2&#xff09;的关系 2. 如何选择 CL1 和 CL…...