C++中的接口有什么用
2023年12月13日,周三上午
今天上午在适配器模式,我发现如果想真正理解适配器模式,就必须学会使用C++中的接口,就必须明白为什么要在C++中使用接口,所以重新学习了一下C++中的接口
目录
- C++中的接口有什么用
- 用代码说明“实现多态性”
- 用代码说明“隐藏实现细节”
- 用代码说明“实现代码解耦“
C++中的接口有什么用
在C++中,虽然没有像其他编程语言(如Java和C#)中的明确接口(interface)概念,但可以使用抽象类来实现类似的功能。
接口在软件开发中起到了以下几个重要的作用:
-
实现多态性:接口提供了一种定义规范的方式,可以通过多态性实现对象的替换和统一的调用方式。通过接口,不同的类可以实现相同的接口,并以统一的方式进行调用。
-
隐藏实现细节:接口定义了一组可供外部使用的方法,同时隐藏了具体实现的细节。这样,使用接口的代码只需要关注接口定义的方法,而不需要了解具体的实现细节。
-
实现代码解耦:通过接口,将不同的部分分离开来,使得代码的耦合度降低。接口作为一个中间层,将不同的模块解耦,使得代码更加灵活和可维护。
-
提高代码的可扩展性:通过接口,可以为系统提供一种扩展的方式。当需要增加新的功能时,只需要实现相应的接口并符合接口定义的规范,而无需修改原有的代码。
用代码说明“实现多态性”
#include <iostream>// 定义接口(抽象类)
class Shape {
public:virtual void draw() = 0; // 纯虚函数
};// 实现接口的类
class Circle : public Shape {
public:void draw() override {std::cout << "Drawing a circle." << std::endl;}
};class Rectangle : public Shape {
public:void draw() override {std::cout << "Drawing a rectangle." << std::endl;}
};int main() {// 创建接口指针,并使用多态性调用不同的实现类的方法Shape* shape1 = new Circle();Shape* shape2 = new Rectangle();shape1->draw(); // 调用Circle类的draw方法shape2->draw(); // 调用Rectangle类的draw方法delete shape1;delete shape2;return 0;
}
在这个例子中,定义了一个接口Shape,其中包含纯虚函数draw()。
然后,创建了两个实现了该接口的类Circle和Rectangle,并分别实现了draw()方法。
在main()函数中,创建了两个接口指针shape1和shape2,分别指向Circle和Rectangle的对象。通过这两个指针,可以以统一的方式调用不同的实现类的方法,实现了多态性。
用代码说明“隐藏实现细节”
#include <iostream>// 定义接口(抽象类)
class Database {
public:virtual void connect() = 0; // 纯虚函数virtual void query(const std::string& sql) = 0; // 纯虚函数
};// 实现接口的类
class MySQLDatabase : public Database {
public:void connect() override {std::cout << "Connected to MySQL database." << std::endl;}void query(const std::string& sql) override {std::cout << "Executing query: " << sql << std::endl;// 实际的查询逻辑}
};int main() {// 使用接口指针调用接口的方法,隐藏了具体实现的细节Database* db = new MySQLDatabase();db->connect();db->query("SELECT * FROM customers");delete db;return 0;
}
在这个例子中,定义了一个接口Database,其中包含纯虚函数connect()和query()。
然后,创建了一个实现了该接口的类MySQLDatabase,并实现了这两个方法。
在main()函数中,通过接口指针db调用接口的方法,而不需要关心具体实现的细节。这样,可以隐藏实现的细节,只需要使用接口提供的方法即可。
为了更好的说明“通过接口隐藏实现细节”,现在我来假设一个场景:
我是一个主程序员,然后还下辖了另一个程序员。
现在我发现程序需要对数据库进行操作,然后我就用抽象类了定义一个数据库操作类,在这个数据库操作类里面用虚函数写了很多我认为程序会使用到的函数。
之后,我把实现这个抽象类——数据库操作类的任务交给了我下辖的程序员。
我下辖的程序员实现后,我只需要通过这个抽象类或者说接口通过指针或引用直接调用我下辖的程序员实现的功能就可以了,我不需要知道他是怎么实现的。
用代码说明“实现代码解耦“
#include <iostream>// 定义接口(抽象类)
class Logger {
public:virtual void log(const std::string& message) = 0; // 纯虚函数
};// 实现接口的类
class ConsoleLogger : public Logger {
public:void log(const std::string& message) override {std::cout << "Console Logger: " << message << std::endl;}
};class FileLogger : public Logger {
public:void log(const std::string& message) override {std::cout << "File Logger: " << message << std::endl;// 将日志写入文件}
};class LogManager {
private:Logger* logger;public:LogManager(Logger* logger) {this->logger = logger;}void doLog(const std::string& message) {logger->log(message);}
};int main()
{// 创建不同的日志记录器对象,并将其注入到日志管理器中Logger* consoleLogger = new ConsoleLogger();Logger* fileLogger = new FileLogger();LogManager logManager1(consoleLogger);LogManager logManager2(fileLogger);// 调用日志管理器的方法,实现了代码的解耦 logManager1.doLog("This is a log message from console logger."); logManager2.doLog("This is a log message from file logger.");delete consoleLogger; delete fileLogger;return 0;
}
在这个例子中,定义了一个接口Logger,其中包含纯虚函数log()。
然后,创建了两个实现了该接口的类ConsoleLogger和FileLogger,并分别实现了log()方法。
接下来,创建了一个LogManager类,其中包含一个Logger指针成员变量。在LogManager的构造函数中,将不同的日志记录器对象注入到LogManager中。
在main()函数中,创建了两个LogManager对象logManager1和logManager2,分别使用了ConsoleLogger和FileLogger作为日志记录器。通过调用LogManager的方法,实现了代码的解耦,不同的日志记录器对象可以被注入到LogManager中,实现了灵活的日志记录功能。
相关文章:
C++中的接口有什么用
2023年12月13日,周三上午 今天上午在适配器模式,我发现如果想真正理解适配器模式,就必须学会使用C中的接口,就必须明白为什么要在C中使用接口,所以重新学习了一下C中的接口 目录 C中的接口有什么用用代码说明“实现多…...
el-table合并相同数据的单元格
相同的数据合并单元格 <el-table :data"userList" :span-method"objectSpanMethod" border><el-table-column type"selection" width"50" align"center" /><el-table-column label"用户名称" a…...
Verilog Systemverilog define宏定义
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 文章前情预告一、define是个啥?二、为什么要使用define三、怎么使用define四、define的横向拓展五、define思想在生活中的体现!六、结论七、参考资料八、…...
51单片机应用从零开始(十一)·数组函数、指针函数
51单片机应用从零开始(九)数组-CSDN博客 51单片机应用从零开始(十)指针-CSDN博客 目录 1. 用数组作函数参数控制流水花样 2. 用指针作函数参数控制 P0 口 8 位 LED 流水点亮 1. 用数组作函数参数控制流水花样 要在51单片机中…...
【PostgreSQL】从零开始:(八)PostgreSQL-数据库PSQL元命令
元命令 postgres# \? General\bind [PARAM]... set query parameters\copyright show PostgreSQL usage and distribution terms\crosstabview [COLUMNS] execute query and display result in crosstab\errverbose show most recent error…...
02 使用Vite创建Vue3项目
概述 A Vue project is structured similarly to a lot of modern node-based apps and contains the following: A package.json fileA node_modules folder in the root of your projectVarious other configuration files are usually contained at the root level, such …...
Shell三剑客:sed(简介)
一、前言 Stream EDitor:流编辑 sed 是一种在线的、非交互式的编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后&…...
tp连接数据库
ThinkPHP内置了抽象数据库访问层,把不同的数据库操作封装起来,我们只需要使用公共的Db类进行操作,而无需针对不同的数据库写不同的代码和底层实现,Db类会自动调用相应的数据库驱动来处理。采用PDO方式,目前包含了Mysql…...
jmeter,断言:响应断言、Json断言
一、响应断言 接口A请求正常返回值如下: {"status": 10013, "message": "user sign timeout"} 在该接口下创建【响应断言】元件,配置如下: 若断言成功,则查看结果树的接口显示绿色,若…...
dockerfite创建镜像---INMP+wordpress
搭建dockerfile---lnmp 在192.168.10.201 使用 Docker 构建 LNMP 环境并运行 Wordpress 网站平台 [rootdocker1 opt]# mkdir nginx mysql php [rootdocker1 opt]# ls #分别拖入四个包: nginx-1.22.0.tar.gz mysql-boost-5.7.20.tar.gz php-7.1.10.tar.bz2 wor…...
服务器数据恢复—raid5热备盘未激活崩溃导致上层oracle数据丢失的数据恢复案例
服务器数据恢复环境: 某品牌X系列服务器,4块SAS硬盘组建了一组RAID5阵列,还有1块磁盘作为热备盘使用。服务器上层安装的linux操作系统,操作系统上部署了一个基于oracle数据库的OA(oracle已经不再为该OA系统提供后续服务…...
生产派工自动化:MES系统的关键作用
随着制造业的数字化转型和智能化发展,生产派工自动化成为了提高生产效率、降低成本,并实现优质产品生产的关键要素之一。制造执行系统(MES)在派工自动化中发挥着重要作用,通过实时数据采集和智能调度,优化生…...
netty-daxin-2(netty常用事件讲解)
文章目录 netty常用事件讲解ChannelHandler接口ChannelHandler适配器类ChannelInboundHandler 子接口Channel 的状态调用时机ChannelHandler 生命周期示例NettServer&CustomizeInboundHandlerNettyClient测试分析 ChannelInboundHandlerAdapter适配器类SimpleChannelInboun…...
使用playbook部署k8s集群
1.部署ansible集群 使用python脚本一个简单的搭建ansible集群-CSDN博客 2.ansible命令搭建k8s: 1.主机规划: 节点IP地址操作系统配置server192.168.174.150centos7.92G2核client1192.168.174.151centos7.92G2核client2192.168.174.152centos7.92G2 …...
Python基础入门第四节,第五节课笔记
第四节 第一个条件语句 if 条件: 条件成立执行的代码1 条件成立执行的代码2 ...... else: 条件不成立执行的代码1 条件不成立执行的代码2 …… 代码如下: 身高 float(input("请输入您的身高(米):")) if 身高 >1.3:print(f您的身高是{身高},已经超过1.3米,您需…...
基于Java SSM框架实现智能停车场系统项目【项目源码+论文说明】
基于java的SSM框架实现智能停车场系统演示 摘要 本论文主要论述了如何使用JAVA语言开发一个智能停车场管理系统,本系统将严格按照软件开发流程进行各个阶段的工作,采用B/S架构,面向对象编程思想进行项目开发。在引言中,作者将论述…...
React系列:useEffect的使用
useEffect的使用 useEffect的第二个参数不同,useEffect的加载不同 当第二个参数为没有的时候 只在组件初始渲染和组件更新之后加载当第二个参数为[] 的时候 只在初始渲染之后加载当第二个参数为[有依赖] 的时候 只在初始渲染之后和依赖修改的时候进行加载 functi…...
Ps:形状工具 - 描边选项
在形状工具的工具选项栏或“属性”面板中,单击“设置形状描边类型” Set shape stroke type菜单图标可打开“描边选项” Stroke Options面板。 描边预设 Stroke Type 默认列出了实线、虚线和点线三种类型的描边,单击可应用。 自己创建并存储的描边类型&a…...
C#基础知识 - 变量、常量与数据类型篇
C#基础知识 - 变量、常量与数据类型篇 第3节 变量、常量与数据类型3.1 C#变量3.1.1 变量使用3.1.2 自定义变量3.1.2 接收用户输入 3.2 C#常量3.2.1 常量的使用 3.3 C#数据类型3.3.1 数据类型之值类型3.3.2 数据类型之引用类型 更多C#基础知识详解请查看:C#基础知识 …...
Java面向对象思想以及原理以及内存图解
文章目录 什么是面向对象面向对象和面向过程区别创建一个对象用什么运算符?面向对象实现伪代码面向对象三大特征类和对象的关系。 基础案例代码实现实例化创建car对象时car引用的内存图对象调用方法过程 成员变量和局部变量作用范围在内存中的位置 关于对象的引用关系简介相关…...
网络编程(Modbus进阶)
思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...
地震勘探——干扰波识别、井中地震时距曲线特点
目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波:可以用来解决所提出的地质任务的波;干扰波:所有妨碍辨认、追踪有效波的其他波。 地震勘探中,有效波和干扰波是相对的。例如,在反射波…...
模型参数、模型存储精度、参数与显存
模型参数量衡量单位 M:百万(Million) B:十亿(Billion) 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的,但是一个参数所表示多少字节不一定,需要看这个参数以什么…...
边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...
【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...
Mac软件卸载指南,简单易懂!
刚和Adobe分手,它却总在Library里给你写"回忆录"?卸载的Final Cut Pro像电子幽灵般阴魂不散?总是会有残留文件,别慌!这份Mac软件卸载指南,将用最硬核的方式教你"数字分手术"࿰…...
tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...
听写流程自动化实践,轻量级教育辅助
随着智能教育工具的发展,越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式,也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建,…...
HarmonyOS运动开发:如何用mpchart绘制运动配速图表
##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在运动类应用中,运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据,如配速、距离、卡路里消耗等,用户可以更清晰…...
计算机基础知识解析:从应用到架构的全面拆解
目录 前言 1、 计算机的应用领域:无处不在的数字助手 2、 计算机的进化史:从算盘到量子计算 3、计算机的分类:不止 “台式机和笔记本” 4、计算机的组件:硬件与软件的协同 4.1 硬件:五大核心部件 4.2 软件&#…...
