突破编程_C++_设计模式(组合模式)
1 组合模式的基本概念
C++中的组合模式是一种对象结构型模式,它将多个对象组合成树形结构,以表示具有整体-部分关系的层次结构。在这个模式中,对单个对象(叶子对象)与组合对象(容器对象)的使用具有一致性,因此组合模式又称为部分-整体模式。
组合模式的主要概念包括:
(1)抽象组件(Component): 这是组合模式中最重要的接口或抽象类,它声明了访问及管理子组件的方法,如增加子组件、删除子组件、获取子组件等。所有叶子组件和容器组件都应当实现这个接口。
(2)叶子组件(Leaf): 这是组合模式中的基本对象,它实现了抽象组件中定义的行为,并且没有子组件。
(3)容器组件(Composite): 这是包含子组件的组合对象,它可以包含叶子组件和其他容器组件,形成一个树形结构。容器组件实现了抽象组件中定义的行为,并提供了管理和操作其子组件的方法。
使用组合模式的主要优点在于,客户端可以一致地处理单个对象和组合对象,无需关心它们之间的具体差异。这使得代码更加简洁、清晰,并提高了系统的灵活性和可维护性。
组合模式在多种场景中都非常有用,例如当需要表示具有整体与部分关系的层次结构时,或者当希望忽略整体与部分的差异,以一种统一的方式处理它们时。此外,当系统中需要处理树形结构,或者需要动态地增加新的类型时,组合模式也是一个很好的选择。
2 组合模式的实现步骤
组合模式的实现步骤如下:
(1)定义抽象组件(Component)接口:
创建一个抽象类或接口,表示组件的通用行为。
在该接口中,定义用于操作组件的方法,比如添加、删除子组件,获取子组件等。
(2)实现叶子组件(Leaf)类:
创建一个或多个叶子组件类,继承或实现抽象组件接口。
在叶子组件类中,实现抽象组件接口中定义的方法,但通常叶子组件不会有子组件,所以添加和删除子组件的方法可能会抛出异常或执行空操作。
(3)实现容器组件(Composite)类:
创建一个容器组件类,继承或实现抽象组件接口。
在容器组件类中,除了实现抽象组件接口中定义的方法外,还需要维护一个子组件列表。
提供方法来添加、删除和获取子组件,并可以递归地调用子组件的相应方法。
(4)组合组件:
在客户端代码中,可以创建叶子组件和容器组件的实例,并将它们组合起来形成树形结构。
客户端可以通过容器组件的接口来操作整个树形结构,无论是访问叶子组件还是递归地操作子树。
如下为样例代码:
#include <iostream>
#include <vector>
#include <string>
#include <memory>
#include <algorithm> // 定义抽象组件(Component)接口
class Component {
public:virtual ~Component() {}virtual void operation() const = 0;virtual void add(std::shared_ptr<Component> component) = 0;virtual void remove(Component* component) = 0;virtual Component* getChild(int index) = 0;virtual int getNumChildren() const = 0;virtual bool isComposite() const = 0;virtual bool isLeaf() const = 0;
};// 实现叶子组件(Leaf)类
class Leaf : public Component {
public:Leaf(const std::string& name) : m_name(name) {}void operation() const override {std::cout << "Leaf operation: " << m_name << std::endl;}void add(std::shared_ptr<Component> component) override {std::cout << "Leaf cannot have children." << std::endl;}void remove(Component* component) override {std::cout << "Leaf cannot remove children." << std::endl;}Component* getChild(int index) override {return nullptr;}int getNumChildren() const override {return 0;}bool isComposite() const override {return false;}bool isLeaf() const override {return true;}private:std::string m_name;
};// 实现容器组件(Composite)类
class Composite : public Component {
public:Composite(const std::string& name) : m_name(name) {}void operation() const override {std::cout << "Composite operation: " << m_name << std::endl;for (const auto& child : m_children) {child->operation();}}void add(std::shared_ptr<Component> component) override {m_children.push_back(std::move(component));}void remove(Component* component) override {auto it = std::find_if(m_children.begin(), m_children.end(),[component](const std::shared_ptr<Component>& c) {return c.get() == component;});if (it != m_children.end()) {m_children.erase(it);}else {std::cout << "Component not found in children." << std::endl;}}Component* getChild(int index) override {if (index < 0 || index >= m_children.size()) {return nullptr;}return m_children[index].get();}int getNumChildren() const override {return m_children.size();}bool isComposite() const override {return true;}bool isLeaf() const override {return false;}private:std::string m_name;std::vector<std::shared_ptr<Component>> m_children;
};// 组合组件
int main()
{// 创建叶子组件和容器组件实例 std::shared_ptr<Leaf> leaf1 = std::make_shared<Leaf>("Leaf1");std::shared_ptr<Leaf> leaf2 = std::make_shared<Leaf>("Leaf2");std::shared_ptr<Composite> composite = std::make_shared<Composite>("Composite");// 将叶子组件添加到容器组件中 composite->add(std::move(leaf1));composite->add(std::move(leaf2));// 执行操作 composite->operation();// 移除组件(如果需要) // composite->remove(leaf1.get()); return 0;
}
上面代码的输出为:
Composite operation: Composite
Leaf operation: Leaf1
Leaf operation: Leaf2
在这个示例中,定义了一个 Component 抽象类,它包含了组件的通用行为。Leaf 类表示叶子组件,它实现了 Component 接口,但通常不会有子组件。Composite 类表示容器组件,它同样实现了 Component 接口,并维护了一个子组件列表。
这个示例展示了组合模式的基本结构和使用方式。可以根据需要扩展这个示例,添加更多的组件类型、方法或操作,以适应具体应用场景。
3 组合模式的应用场景
C++ 中的组合模式应用场景主要涉及到需要表示对象的整体-部分层次结构,并希望客户端能够以统一的方式处理单个对象和对象组合的情况。以下是一些具体的应用场景:
(1)文件系统: 文件系统中的文件和文件夹是典型的组合模式应用场景。文件夹可以包含文件和其他文件夹,形成树形结构。通过组合模式,用户可以统一地处理文件和文件夹,如进行遍历、搜索、删除等操作,而无需区分它们的具体类型。
(2)图形用户界面(GUI): 在GUI中,窗口、面板、按钮、文本框等组件经常需要组合使用。组合模式允许将这些组件组织成树形结构,使得用户可以通过统一的接口来管理和操作这些组件。例如,一个窗口可以包含多个面板,而面板又可以包含按钮和文本框等子组件。
(3)菜单系统: 在复杂的菜单系统中,菜单项可能包含子菜单,形成多级菜单结构。通过组合模式,可以方便地管理这种多级菜单,并允许用户通过统一的接口进行导航和操作。
(4)部门组织架构: 在企业或组织的部门结构中,部门可能包含子部门或员工,形成层次化的组织结构。组合模式可以用于表示这种组织结构,并允许管理层以统一的方式管理和查询各个部门或员工的信息。
在这些应用场景中,组合模式使得客户端代码更加简洁和清晰,因为客户端只需要与抽象组件接口进行交互,而无需关心具体是处理单个对象还是对象组合。此外,组合模式还具有良好的扩展性,可以方便地添加新的组件类型或修改现有组件的行为,而无需修改客户端代码。
3.1 组合模式应用于文件系统
C++ 组合模式应用于文件系统的示例可以描述如下:
首先,定义一个 FileSystemElement 抽象类,它表示文件系统中的元素,可以是文件或文件夹。这个类将声明一些基本的操作,如名称的获取和设置。
#include <iostream>
#include <string>
#include <vector>
#include <memory> class FileSystemElement {
public:virtual ~FileSystemElement() {}virtual std::string getName() const = 0;virtual void setName(const std::string& name) = 0;// 可能还有其他通用操作,如访问权限设置等
};
然后,实现 File 类,表示文件系统中的一个文件。它继承自 FileSystemElement,并实现其中的方法。
class File : public FileSystemElement {
public:File(const std::string& name) : name(name) {}std::string getName() const override {return name;}void setName(const std::string& name) override {this->name = name;}// 文件特有的操作,如读取内容、写入内容等 private:std::string name;
};
接下来,实现 Directory 类,表示文件系统中的一个文件夹。它也继承自 FileSystemElement,并实现其中的方法。此外,它还需要维护一个包含子元素的列表。
class Directory : public FileSystemElement {
public:Directory(const std::string& name) : name(name) {}std::string getName() const override {return name;}void setName(const std::string& name) override {this->name = name;}void addChild(std::shared_ptr<FileSystemElement> child) {children.push_back(child);}// 文件夹特有的操作,如遍历子元素、删除子元素等 void traverse() const {for (const auto& child : children) {std::cout << child->getName() << std::endl;if (auto dir = dynamic_cast<const Directory*>(child.get())) {dir->traverse(); // 递归遍历子文件夹 }}}private:std::string name;std::vector<std::shared_ptr<FileSystemElement>> children;
};
现在,可以使用这些类来构建文件系统树:
int main()
{// 创建文件夹和文件对象 std::shared_ptr<Directory> root = std::make_shared<Directory>("root");std::shared_ptr<Directory> dir1 = std::make_shared<Directory>("dir1");std::shared_ptr<File> file1 = std::make_shared<File>("file1.txt");std::shared_ptr<File> file2 = std::make_shared<File>("file2.txt");// 将文件和文件夹添加到树中 root->addChild(dir1);dir1->addChild(file1);dir1->addChild(file2);// 遍历并打印文件系统树的内容 root->traverse();return 0;
}
上面这些代码的输出为:
dir1
file1.txt
file2.txt
这个简单的示例展示了如何使用组合模式来构建一个文件系统的树形结构,并允许通过统一的方式处理文件和文件夹。在实际应用中,文件系统通常会有更多的操作和功能,如文件的读写、权限管理、路径解析等,但这些都可以基于这个基本框架进行扩展。
3.2 组合模式应用于图形用户界面(GUI)
C++ 组合模式应用于图形用户界面(GUI)的示例可以描述如下:
首先,定义一个 GUIComponent 抽象类,它表示 GUI 中的一个组件。这个类将声明一些基本的操作,如绘制、添加子组件等。
#include <iostream>
#include <vector>
#include <memory>
#include <string>
#include <algorithm> class GUIComponent {
public:virtual ~GUIComponent() {}virtual void draw() const = 0;virtual void add(std::shared_ptr<GUIComponent> component) = 0;virtual void remove(GUIComponent* component) = 0;// 可能还有其他通用操作,如设置位置、大小等
};
然后,实现 LeafComponent 类,表示 GUI 中的一个叶子组件,比如一个按钮或文本框。它继承自 GUIComponent,并实现其中的方法。
class LeafComponent : public GUIComponent {
public:LeafComponent(const std::string& name) : name(name) {}void draw() const override {std::cout << "Drawing leaf component: " << name << std::endl;}void add(std::shared_ptr<GUIComponent> component) override {// 叶子组件不能添加子组件,可以抛出异常或忽略 std::cout << "Leaf component cannot add child components." << std::endl;}void remove(GUIComponent* component) override {// 叶子组件没有子组件可移除,可以抛出异常或忽略 std::cout << "Leaf component has no child components to remove." << std::endl;}private:std::string name;
};
接下来,实现 CompositeComponent 类,表示 GUI 中的一个容器组件,比如一个窗口或面板。它也继承自 GUIComponent,并实现其中的方法。此外,它还需要维护一个包含子组件的列表。
class CompositeComponent : public GUIComponent {
public:CompositeComponent(const std::string& name) : name(name) {}void draw() const override {std::cout << "Drawing composite component: " << name << std::endl;for (const auto& child : children) {child->draw(); // 递归绘制子组件 }}void add(std::shared_ptr<GUIComponent> component) override {children.push_back(std::move(component));}void remove(GUIComponent* component) override {auto it = std::find_if(children.begin(), children.end(),[component](const std::shared_ptr<GUIComponent>& c) {return c.get() == component;});if (it != children.end()) {children.erase(it);}else {std::cout << "Component not found in children." << std::endl;}}private:std::string name;std::vector<std::shared_ptr<GUIComponent>> children;
};
现在,可以使用这些类来构建GUI:
int main()
{// 创建叶子组件和容器组件对象 std::shared_ptr<LeafComponent> button = std::make_shared<LeafComponent>("Button");std::shared_ptr<LeafComponent> textBox = std::make_shared<LeafComponent>("TextBox");std::shared_ptr<CompositeComponent> window = std::make_shared<CompositeComponent>("Window");// 将叶子组件添加到容器组件中 window->add(button);window->add(textBox);// 绘制GUI window->draw();// 移除组件(如果需要) // window->remove(button.get()); // 假设想要移除按钮 return 0;
}
上面这些代码的输出为:
Drawing composite component: Window
Drawing leaf component: Button
Drawing leaf component: TextBox
这个简单的示例展示了如何使用组合模式来构建一个GUI,并允许通过统一的方式处理容器组件和叶子组件。在实际应用中,GUI组件通常会有更多的属性和方法,比如处理用户事件、更新状态等,但这些都可以基于这个基本框架进行扩展。
4 组合模式的优点与缺点
C++ 组合模式的优点主要包括:
(1)结构清晰: 组合模式可以清晰地定义分层次的复杂对象,表示对象的全部或部分层次,使得客户端能够忽略对象组合和单个对象的区别,一致地对待组合结构中的所有对象。这有助于简化客户端代码,提高代码的可读性和可维护性。
(2)扩展性好: 在组合模式中,增加新的容器构件和叶子构件都很方便,无需对现有类库进行任何修改,这符合“开闭原则”。这使得系统的扩展和修改变得更加容易,降低了系统的耦合度。
(3)灵活性高: 组合模式可以灵活地将不同的叶子节点抽象成相同的节点,达成忽略整体-部分差异的目标,最终给用户的是统一的抽象接口。这使得系统能够更灵活地应对各种复杂情况,提高了系统的适应性和灵活性。
然而,C++ 组合模式也存在一些缺点:
(1)设计抽象性: 组合模式可能使设计变得过于抽象和复杂。如果对象的业务规则很复杂,实现组合模式可能会具有很大的挑战性。此外,并非所有的方法都与叶子对象子类都相关联,这可能导致一些不必要的复杂性。
(2)通用性问题: 在某些情况下,只有叶子组件需要定义某些操作,但由于组合模式的通用性,可能不得不在所有组件中定义这些操作,这可能会增加代码的复杂性。
(3)对象创建与转换问题: 当组合深度很大时,创建对象可能会变得非常麻烦,并且会创建大量的子对象。此外,在进行类型转换时,需要避免截断使用范围,否则可能会导致错误。
相关文章:
突破编程_C++_设计模式(组合模式)
1 组合模式的基本概念 C中的组合模式是一种对象结构型模式,它将多个对象组合成树形结构,以表示具有整体-部分关系的层次结构。在这个模式中,对单个对象(叶子对象)与组合对象(容器对象)的使用具…...

010Editor汉化版+下载+注册码+模板bug
项目场景: 这天我想使用我的不知名的一个破解版本的010Edit来查看一个EXE程序,并想使用模板功能,但是发现没有该模板还无法下载最新模板 问题描述 010Edit联网后需要注册码: 010 Editor 激活码生成器 使用方法 参照教程使用0…...
js【详解】BOM
浏览器对象模型 (Browser obiect Mode 简称 BOM) 浏览器对象即 window,调用window对象的属性和方法时,可以省略window window 常用的属性 Navigator 常用于获取浏览器的信息 navigator.userAgent;火狐浏览器范例: “…...
Leetcode 3077. Maximum Strength of K Disjoint Subarrays
Leetcode 3077. Maximum Strength of K Disjoint Subarrays 1. 解题思路 1. 朴素思路2. 算法优化 2. 代码实现 题目链接:3077. Maximum Strength of K Disjoint Subarrays 1. 解题思路 这道题很惭愧没有搞定,思路上出现了差错,导致一直没能…...

【JetsonNano】onnxruntime-gpu 环境编译和安装,支持 Python 和 C++ 开发
1. 设备 2. 环境 sudo apt-get install protobuf-compiler libprotoc-devexport PATH/usr/local/cuda/bin:${PATH} export CUDA_PATH/usr/local/cuda export cuDNN_PATH/usr/lib/aarch64-linux-gnu export CMAKE_ARGS"-DONNX_CUSTOM_PROTOC_EXECUTABLE/usr/bin/protoc&qu…...

知名比特币质押协议项目Babylon确认参加Hack.Summit()2024区块链开发者大会
Babylon项目已确认将派遣其项目代表出席2024年在香港数码港举办的Hack.Summit()2024区块链开发者大会。作为比特币生态的领军项目,Babylon积极参与全球区块链领域的交流与合作,此次出席大会将为其提供一个展示项目进展、交流技术与创新思路的重要平台。B…...

如何学习、上手点云算法(三):用VsCode、Visual Studio来debug基于PCL、Open3D的代码
写在前面 本文内容 以PCL 1.14.0,Open3D0.14.1为例,对基于PCL、Open3D开发的代码进行源码debug; 如何学习、上手点云算法系列: 如何学习、上手点云算法(一):点云基础 如何学习、上手点云算法(二):点云处理相…...
【干货】alzet渗透泵操作说明
alzet渗透泵是一款小型、可植入式的胶囊渗透泵产品,此产品由于其独特的渗透原理,深受广大科研人员的喜爱。该泵可适用于小鼠、大鼠及其他实验动物的研究,并且alzet渗透泵可减轻科研人员夜间及周末给药的困扰。alzet渗透泵无需外部连接或频繁处…...

CVPR 2022 Oral | Bailando: 基于编舞记忆和Actor-Critic GPT的3D舞蹈生成
目录 测试结果: 02 提出的方法 测试结果: 预测有3个步骤,速度比较慢 02 提出的方法 1. 针对舞蹈序列的VQ-VAE和编舞记忆 与之前的方法不同,我们不学习从音频特征到 3D 关键点序列的连续域的直接映射。相反,我们先让…...
解读电影级视频生成模型 MovieFactory
Diffusion Models视频生成-博客汇总 前言:MovieFactory是第一个全自动电影生成模型,可以根据用户输入的文本信息自动扩写剧本,并生成电影级视频。其中针对预训练的图像生成模型与视频模型之间的gap提出了微调方法非常值得借鉴。这篇博客详细解读一下这篇论文《MovieFactory:…...

【Python从入门到进阶】50、当当网Scrapy项目实战(三)
接上篇《49、当当网Scrapy项目实战(二)》 上一篇我们讲解了的Spider与item之间的关系,以及如何使用item,以及使用pipelines管道进行数据下载的操作,本篇我们来讲解Scrapy的多页面下载如何实现。 一、多页面下载原理分…...
【调试记录】vscode远程连接问题汇总
1. kex_exchange_identification kex_exchange_identification: read: Connection reset by xxx.xx.xx.x 一直连不上实验室的服务器,用PUTTY和Mobaxterm也不行(报错:Remote side unexpectedly closed network connection)。已知…...

基于springboot的疾病防控综合系统
采用技术 基于springboot的疾病防控综合系统的设计与实现~ 开发语言:Java 数据库:MySQL 技术:SpringBootMyBatis 工具:IDEA/Ecilpse、Navicat、Maven 系统效果展示 用户功能效果 打卡管理 接种记录查看 公告信息查看 社区…...

js实现文本内容过长中间显示...两端正常展示
实现效果 实现思路 获取标题盒子的真实宽度, 我这里用的是clientWidth;获取文本内容所占的实际宽度;根据文字的大小计算出每个文字所占的宽度;判断文本内容的实际宽度是否超出了标题盒子的宽度;通过文字所占的宽度累加之和与标题…...

Buran勒索病毒通过Microsoft Excel Web查询文件进行传播
Buran勒索病毒首次出现在2019年5月,是一款新型的基于RaaS模式进行传播的新型勒索病毒,在一个著名的俄罗斯论坛中进行销售,与其他基于RaaS勒索病毒(如GandCrab)获得30%-40%的收入不同,Buran勒索病毒的作者仅占感染产生的25%的收入,…...

中间件 | Redis - [基本信息]
INDEX 1 常规用法2 QPS3 pipeline 1 常规用法 分布式锁 最常见用法,需要注意分布式锁的redis需要单点 分布式事务 分布式事务中,核心的技术难点其实是分布式事务这个事本身作为数据的持久化 2PC,比如 seata 的 AT 模式下,将 un…...
【Docker】Neo4j 容器化部署
Neo4j环境标准软件基于Bitnami neo4j 构建。当前版本为5.17.0 你可以通过轻云UC部署工具直接安装部署,也可以手动按如下文档操作,该项目已经全面开源,可以从如下环境获取 配置文件地址: https://gitee.com/qingplus/qingcloud-platform Qin…...
Visual studio编译器报1个无法解析的外部命令
解决思路:(以下思路需对照代码进行逐点分析) ①:代码里函数有声明,但是没有定义 (初学者错这个比较多) ②:类中有静态变量成员,没有对它进行初始化(是变量&…...

微信小程序(五十三)修改用户头像与昵称
注释很详细,直接上代码 上一篇 新增内容: 1.外界面个人资料基本模块 2.资料修改界面同步问题实现(细节挺多,考虑了后期转服务器端的方便之处) 源码: app.json {"window": {},"usingCompone…...

VUE3 显示Echarts百度地图
本次实现最终效果 技术基础以及环境要求 vue3 echarts 百度地图API 要求1: VUE3 环境搭建:https://blog.csdn.net/LQ_001/article/details/136293795 要求2: VUE3 echatrs 环境搭建:https://blog.csdn.net/LQ_001/article/details/1363…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...
鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/
使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题:docker pull 失败 网络不同,需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...

Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...
鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南
1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发,使用DevEco Studio作为开发工具,采用Java语言实现,包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...

Golang——6、指针和结构体
指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...

手机平板能效生态设计指令EU 2023/1670标准解读
手机平板能效生态设计指令EU 2023/1670标准解读 以下是针对欧盟《手机和平板电脑生态设计法规》(EU) 2023/1670 的核心解读,综合法规核心要求、最新修正及企业合规要点: 一、法规背景与目标 生效与强制时间 发布于2023年8月31日(OJ公报&…...

【C++】纯虚函数类外可以写实现吗?
1. 答案 先说答案,可以。 2.代码测试 .h头文件 #include <iostream> #include <string>// 抽象基类 class AbstractBase { public:AbstractBase() default;virtual ~AbstractBase() default; // 默认析构函数public:virtual int PureVirtualFunct…...