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

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日&#xff0c;周三上午 今天上午在适配器模式&#xff0c;我发现如果想真正理解适配器模式&#xff0c;就必须学会使用C中的接口&#xff0c;就必须明白为什么要在C中使用接口&#xff0c;所以重新学习了一下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宏定义

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 文章前情预告一、define是个啥&#xff1f;二、为什么要使用define三、怎么使用define四、define的横向拓展五、define思想在生活中的体现!六、结论七、参考资料八、…...

51单片机应用从零开始(十一)·数组函数、指针函数

51单片机应用从零开始&#xff08;九&#xff09;数组-CSDN博客 51单片机应用从零开始&#xff08;十&#xff09;指针-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 是一种在线的、非交互式的编辑器&#xff0c;它一次处理一行内容。处理时&#xff0c;把当前处理的行存储在临时缓冲区中&#xff0c;称为“模式空间”(pattern space)&#xff0c;接着用sed命令处理缓冲区中的内容&#xff0c;处理完成后&…...

tp连接数据库

ThinkPHP内置了抽象数据库访问层&#xff0c;把不同的数据库操作封装起来&#xff0c;我们只需要使用公共的Db类进行操作&#xff0c;而无需针对不同的数据库写不同的代码和底层实现&#xff0c;Db类会自动调用相应的数据库驱动来处理。采用PDO方式&#xff0c;目前包含了Mysql…...

jmeter,断言:响应断言、Json断言

一、响应断言 接口A请求正常返回值如下&#xff1a; {"status": 10013, "message": "user sign timeout"} 在该接口下创建【响应断言】元件&#xff0c;配置如下&#xff1a; 若断言成功&#xff0c;则查看结果树的接口显示绿色&#xff0c;若…...

dockerfite创建镜像---INMP+wordpress

搭建dockerfile---lnmp 在192.168.10.201 使用 Docker 构建 LNMP 环境并运行 Wordpress 网站平台 [rootdocker1 opt]# mkdir nginx mysql php [rootdocker1 opt]# ls #分别拖入四个包&#xff1a; nginx-1.22.0.tar.gz mysql-boost-5.7.20.tar.gz php-7.1.10.tar.bz2 wor…...

服务器数据恢复—raid5热备盘未激活崩溃导致上层oracle数据丢失的数据恢复案例

服务器数据恢复环境&#xff1a; 某品牌X系列服务器&#xff0c;4块SAS硬盘组建了一组RAID5阵列&#xff0c;还有1块磁盘作为热备盘使用。服务器上层安装的linux操作系统&#xff0c;操作系统上部署了一个基于oracle数据库的OA&#xff08;oracle已经不再为该OA系统提供后续服务…...

生产派工自动化:MES系统的关键作用

随着制造业的数字化转型和智能化发展&#xff0c;生产派工自动化成为了提高生产效率、降低成本&#xff0c;并实现优质产品生产的关键要素之一。制造执行系统&#xff08;MES&#xff09;在派工自动化中发挥着重要作用&#xff0c;通过实时数据采集和智能调度&#xff0c;优化生…...

netty-daxin-2(netty常用事件讲解)

文章目录 netty常用事件讲解ChannelHandler接口ChannelHandler适配器类ChannelInboundHandler 子接口Channel 的状态调用时机ChannelHandler 生命周期示例NettServer&CustomizeInboundHandlerNettyClient测试分析 ChannelInboundHandlerAdapter适配器类SimpleChannelInboun…...

使用playbook部署k8s集群

1.部署ansible集群 使用python脚本一个简单的搭建ansible集群-CSDN博客 2.ansible命令搭建k8s&#xff1a; 1.主机规划&#xff1a; 节点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语言开发一个智能停车场管理系统&#xff0c;本系统将严格按照软件开发流程进行各个阶段的工作&#xff0c;采用B/S架构&#xff0c;面向对象编程思想进行项目开发。在引言中&#xff0c;作者将论述…...

React系列:useEffect的使用

useEffect的使用 useEffect的第二个参数不同&#xff0c;useEffect的加载不同 当第二个参数为没有的时候 只在组件初始渲染和组件更新之后加载当第二个参数为[] 的时候 只在初始渲染之后加载当第二个参数为[有依赖] 的时候 只在初始渲染之后和依赖修改的时候进行加载 functi…...

Ps:形状工具 - 描边选项

在形状工具的工具选项栏或“属性”面板中&#xff0c;单击“设置形状描边类型” Set shape stroke type菜单图标可打开“描边选项” Stroke Options面板。 描边预设 Stroke Type 默认列出了实线、虚线和点线三种类型的描边&#xff0c;单击可应用。 自己创建并存储的描边类型&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#基础知识详解请查看&#xff1a;C#基础知识 …...

Java面向对象思想以及原理以及内存图解

文章目录 什么是面向对象面向对象和面向过程区别创建一个对象用什么运算符?面向对象实现伪代码面向对象三大特征类和对象的关系。 基础案例代码实现实例化创建car对象时car引用的内存图对象调用方法过程 成员变量和局部变量作用范围在内存中的位置 关于对象的引用关系简介相关…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题&#xff1a;map 的 key 可以是什么类型&#xff1f;哪些不可以&#xff1f; 在 Golang 的面试中&#xff0c;map 类型的使用是一个常见的考点&#xff0c;其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

什么是库存周转?如何用进销存系统提高库存周转率?

你可能听说过这样一句话&#xff1a; “利润不是赚出来的&#xff0c;是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业&#xff0c;很多企业看着销售不错&#xff0c;账上却没钱、利润也不见了&#xff0c;一翻库存才发现&#xff1a; 一堆卖不动的旧货…...

现代密码学 | 椭圆曲线密码学—附py代码

Elliptic Curve Cryptography 椭圆曲线密码学&#xff08;ECC&#xff09;是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础&#xff0c;例如椭圆曲线数字签…...

关于 WASM:1. WASM 基础原理

一、WASM 简介 1.1 WebAssembly 是什么&#xff1f; WebAssembly&#xff08;WASM&#xff09; 是一种能在现代浏览器中高效运行的二进制指令格式&#xff0c;它不是传统的编程语言&#xff0c;而是一种 低级字节码格式&#xff0c;可由高级语言&#xff08;如 C、C、Rust&am…...

C++:多态机制详解

目录 一. 多态的概念 1.静态多态&#xff08;编译时多态&#xff09; 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1&#xff09;.协变 2&#xff09;.析构函数的重写 5.override 和 final关键字 1&#…...

CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝

目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为&#xff1a;一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...

【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)

前言&#xff1a; 双亲委派机制对于面试这块来说非常重要&#xff0c;在实际开发中也是经常遇见需要打破双亲委派的需求&#xff0c;今天我们一起来探索一下什么是双亲委派机制&#xff0c;在此之前我们先介绍一下类的加载器。 目录 ​编辑 前言&#xff1a; 类加载器 1. …...

windows系统MySQL安装文档

概览&#xff1a;本文讨论了MySQL的安装、使用过程中涉及的解压、配置、初始化、注册服务、启动、修改密码、登录、退出以及卸载等相关内容&#xff0c;为学习者提供全面的操作指导。关键要点包括&#xff1a; 解压 &#xff1a;下载完成后解压压缩包&#xff0c;得到MySQL 8.…...

如何配置一个sql server使得其它用户可以通过excel odbc获取数据

要让其他用户通过 Excel 使用 ODBC 连接到 SQL Server 获取数据&#xff0c;你需要完成以下配置步骤&#xff1a; ✅ 一、在 SQL Server 端配置&#xff08;服务器设置&#xff09; 1. 启用 TCP/IP 协议 打开 “SQL Server 配置管理器”。导航到&#xff1a;SQL Server 网络配…...

前端开发者常用网站

Can I use网站&#xff1a;一个查询网页技术兼容性的网站 一个查询网页技术兼容性的网站Can I use&#xff1a;Can I use... Support tables for HTML5, CSS3, etc (查询浏览器对HTML5的支持情况) 权威网站&#xff1a;MDN JavaScript权威网站&#xff1a;JavaScript | MDN...