《C++ 小程序编写系列》(第六部)

前言:从多态到泛型 ——C++ 编程的进阶之路

在第五部中,我们通过继承与多态实现了管理员、读者等多角色的权限分离,以及图书、期刊等不同资源的统一管理。但系统仍存在局限性:所有数据类型(图书 ID、读者编号、借阅日期等)均为固定类型(如int、string),若需支持自定义类型(如 ISBN 结构体、自定义日期类)或扩展数据格式(如批量导入 Excel 数据),则需大量修改原有代码。

本系列第六部将通过模板编程STL(标准模板库)解决这一问题,打造一个 “一次编写、多类型适配” 的泛型化图书管理系统。核心目标包括:

  1. 用类模板实现通用数据容器,支持图书、读者、借阅记录等多类型数据的统一存储;
  1. 用函数模板封装通用操作(排序、查找、过滤),适配不同数据类型的业务逻辑;
  1. 结合 STL 容器(vector、map、set)与算法(sort、find_if)优化数据管理效率;
  1. 兼容第五部的多角色权限系统,实现泛型与多态的协同工作。

第一章:泛型编程基础 —— 模板的核心语法

1.1 类模板:通用数据载体的设计

类模板允许我们定义 “数据类型参数化” 的类,例如通用的 “数据存储容器”,可适配图书、读者、借阅记录等任意类型:

// 通用数据容器模板(替代第五部的固定类型数组)

template T>

class DataContainer {

private:

vector // 借助STL vector实现动态存储

public:

// 添加数据(自动适配T类型)

void addData(const T& data) {

dataList.push_back(data);

}

// 查找数据(接收自定义匹配规则)

vector<T> findData(function(const T&)> matchRule) {

vector> result;

for (const auto& data : dataList) {

if (matchRule(data)) {

result.push_back(data);

}

}

return result;

}

// 排序数据(接收自定义比较规则)

void sortData(function T&, const T&)> compareRule) {

sort(dataList.begin(), dataList.end(), compareRule);

}

// 其他通用方法:删除、遍历、清空...

};

关键优势:无需为图书(Book)、读者(Reader)分别定义容器类,一套代码适配所有类型,且借助vector自动处理内存分配与扩容。

1.2 函数模板:通用业务逻辑的封装

函数模板用于封装与数据类型无关的逻辑,例如数据校验、格式转换等。以 “借阅记录有效性检查” 为例:

// 通用数据有效性校验模板

template >

bool isValidData(const T& data) {

// 利用C++11的type_traits实现类型差异化校验

if constexpr (is_same_v {

// 借阅记录:借阅日期 归还日期

return data.borrowDate Date;

} else if constexpr (is_same_v

// 图书:ID非空、库存量 >= 0

return !data.bookId.empty() && data.stock >= 0;

} else if constexpr (is_same_v<T, Reader>) {

// 读者:编号非空、年龄 >= 0

return !data.readerId.empty() && data.age >= 0;

} else {

// 默认:自定义类型需自行扩展校验逻辑

return true;

}

}

核心特性:通过constexpr与type_traits实现编译期类型判断,避免运行时开销,同时支持类型的灵活扩展。


第二章:泛型化图书管理系统的架构升级

2.1 系统核心组件重构(兼容第五部)

基于模板与 STL,重构第五部的核心类,保持多角色权限体系不变,仅优化数据存储与操作逻辑:

组件

第五部实现(固定类型)

第六部实现(泛型化)

图书存储

Book books[100](静态数组)

DataContainer bookContainer

读者存储

Reader readers[100]

DataContainer

借阅记录存储

独立数组

DataContainer<BorrowRecord> borrowContainer

查找逻辑

硬编码条件判断

函数对象(function)传入匹配规则

排序逻辑

针对特定类型的排序函数

通用sortData+ 自定义比较规则

2.2 关键业务场景实现
场景 1:多条件查找图书(支持不同查询维度)

// 示例:查找“计算机类”且“库存量>0”的图书

auto computerBooks = bookContainer.findData([](const Book& book) {

return book.category == "计算机" && book.stock > 0;

});

// 示例:查找“2024年之后出版”的图书

auto newBooks = bookContainer.findData([](const Book& book) {

return book.publishYear >= 2024;

});

优势:无需修改容器类代码,仅通过 lambda 表达式传入查询条件,支持无限扩展查询维度。

场景 2:自定义排序(适配不同业务需求)

// 示例1:按图书库存量降序排序

bookContainer.sortData([](const Book& a, const Book& b) {

return a.stock > b.stock;

});

// 示例2:按读者年龄升序排序

readerContainer.sortData([](const Reader& a, const Reader& b) {

return a.age });

原理:借助 STL 的sort算法,通过函数对象传递比较规则,实现对任意类型数据的排序。

场景 3:多类型数据批量导入

// 通用数据导入模板(支持从文件导入任意类型)

template >

bool importDataFromFile(const string& filePath, DataContainer {

ifstream file(filePath);

if (!file.is_open()) return false;

T data;

while (file >> data) { // 需为自定义类型重载>>运算符

if (isValidData(data)) { // 调用通用校验模板

container.addData(data);

}

}

file.close();

return true;

}

// 调用示例:导入图书数据和读者数据

importDataFromFile<Book>("books.txt", bookContainer);

importDataFromFile.txt", readerContainer);

扩展性:只需为新数据类型(如Journal期刊)重载输入运算符和校验逻辑,即可直接复用导入功能。


第三章:泛型与多态的协同工作

3.1 模板类中使用多态(角色权限控制)

第五部中通过多态实现了管理员、读者的权限分离,第六部中可在泛型容器中直接存储基类指针,保留多态特性:

// 存储角色基类指针的泛型容器

DataContainer*> roleContainer;

// 添加不同角色(多态特性保留)

roleContainer.addData(new Admin("admin001", "123456"));

roleContainer.addData(new ReaderUser("reader001", "654321", 25));

// 调用多态方法(无需关心具体角色类型)

auto allRoles = roleContainer.findData([](Role* role) {

return true; // 查找所有角色

});

for (auto role : allRoles) {

role->showMenu(); // 动态绑定:管理员显示管理员菜单,读者显示读者菜单

}

核心要点:模板容器支持存储指针类型,结合多态可实现 “通用存储 + 差异化行为”,兼顾灵活性与扩展性。

3.2 模板特化:处理特殊类型的差异化需求

当通用模板无法满足特定类型的需求时,可使用模板特化。例如,为BorrowRecord(借阅记录)特化findData方法,支持按日期范围查询:

// 为BorrowRecord类型特化DataContainer的findData方法

template <>

vectorRecord> DataContainerRecord>::findData(function(const BorrowRecord&)> matchRule) {

// 扩展:先按借阅日期排序,再执行匹配(优化查询效率)

sortData([](const BorrowRecord& a, const BorrowRecord& b) {

return a.borrowDate ;

});

// 调用通用逻辑

return DataContainerRecord>::findData(matchRule);

}

作用:在保持通用逻辑的同时,为特殊类型提供定制化优化,避免 “一刀切” 的设计缺陷。


第四章:系统测试与性能优化

4.1 功能测试(验证泛型兼容性)
  1. 多类型支持测试:分别添加Book、Reader、BorrowRecord数据,验证存储、查找、排序功能正常;
  1. 扩展类型测试:新增Journal(期刊)类,无需修改容器代码,直接复用DataContainer与isValidData模板;
  1. 多态协同测试:通过Role*指针调用不同角色的方法,验证多态行为正常。
4.2 性能优化(STL 的高效使用)
  1. 容器选择:用map存储图书 ID 与图书对象的映射,实现 O (1) 时间复杂度的 ID 查询:

mapMap; // key: 图书ID,value: 图书对象

  1. 算法优化:使用find_if替代手动遍历,结合lambda表达式简化代码:

// 查找ID为"book001"的图书(STL算法版)

auto it = find_if(bookList.begin(), bookList.end(), [](const Book& book) {

return book.bookId == "book001";

});

  1. 内存管理:使用智能指针(shared_ptr)替代裸指针,避免内存泄漏:

DataContainer<shared_ptrContainer;

roleContainer.addData(make_shared>("admin001", "123456"));


总结与后续展望

本章节通过模板与 STL 实现了图书管理系统的泛型化升级,核心收获包括:

  • 掌握类模板与函数模板的定义与使用,实现代码复用;
  • 学会结合 STL 容器与算法优化数据管理,提升开发效率;
  • 理解泛型与多态的协同机制,打造灵活可扩展的系统架构。

后续系列预告:第七部将聚焦C++ 11 + 新特性实战,包括并发编程(thread、mutex)、智能指针深度应用、lambda 表达式高级用法等,进一步提升系统的性能与稳定性。

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

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

相关文章

从图片到JSON:利用DeepSeek-OCR-WEBUI实现SpringBoot表格数据自动提取

从图片到JSON&#xff1a;利用DeepSeek-OCR-WEBUI实现SpringBoot表格数据自动提取 在企业级应用开发中&#xff0c;纸质单据、发票、采购表等结构化文档的数字化处理一直是一个高频且繁琐的任务。传统的人工录入方式不仅效率低&#xff0c;还容易出错。随着AI技术的发展&#…

为何DeepSeek-R1推理更稳定?基于强化学习的数据蒸馏解析

为何DeepSeek-R1推理更稳定&#xff1f;基于强化学习的数据蒸馏解析 1. 模型背景与核心优势 你可能已经注意到&#xff0c;最近一款名为 DeepSeek-R1-Distill-Qwen-1.5B 的模型在多个推理任务中表现异常稳健——无论是解数学题、写代码&#xff0c;还是处理复杂逻辑链&#x…

Qwen1.5-0.5B训练后微调?原生Transformers接入指南

Qwen1.5-0.5B训练后微调&#xff1f;原生Transformers接入指南 1. 背景与目标&#xff1a;为什么用一个模型做两件事&#xff1f; 你有没有遇到过这种情况&#xff1a;想做个情感分析功能&#xff0c;得加载BERT&#xff1b;再加个对话机器人&#xff0c;又得上LLM。结果显存…

Sambert语音服务日志分析:错误排查与性能监控

Sambert语音服务日志分析&#xff1a;错误排查与性能监控 1. 引言&#xff1a;为什么日志分析是语音服务稳定运行的关键 你有没有遇到过这种情况&#xff1a;用户反馈语音合成突然变慢&#xff0c;甚至返回空白音频&#xff0c;而服务进程却显示正常运行&#xff1f;或者在高…

测试镜像优化建议:小而美,适合入门和测试场景

测试镜像优化建议&#xff1a;小而美&#xff0c;适合入门和测试场景 1. 引言&#xff1a;为什么需要轻量化的测试镜像&#xff1f; 在开发和测试过程中&#xff0c;我们常常需要快速验证某个功能、服务或脚本的可行性。这时候&#xff0c;一个启动快、结构简单、易于调试的测…

GPT-OSS-20B推理延迟优化:批处理参数调整案例

GPT-OSS-20B推理延迟优化&#xff1a;批处理参数调整案例 1. 背景与目标&#xff1a;为什么需要优化GPT-OSS-20B的推理延迟&#xff1f; 你有没有遇到过这样的情况&#xff1a;模型部署好了&#xff0c;界面也打开了&#xff0c;但每次提问都要等好几秒才出结果&#xff1f;尤…

Qwen3-Embedding-4B启动报错?环境配置问题解决案例

Qwen3-Embedding-4B启动报错&#xff1f;环境配置问题解决案例 在部署大模型服务时&#xff0c;即使使用了官方推荐的框架和镜像&#xff0c;也常常会遇到意想不到的启动问题。本文聚焦一个真实场景&#xff1a;基于SGlang部署Qwen3-Embedding-4B向量服务时出现启动失败的情况…

PyTorch-2.x Universal镜像实测:科学计算库调用指南

PyTorch-2.x Universal镜像实测&#xff1a;科学计算库调用指南 1. 镜像简介与核心价值 你是不是也经历过这样的场景&#xff1a;刚搭好一个深度学习环境&#xff0c;结果跑代码时发现少装了pandas&#xff0c;画图又缺了matplotlib&#xff0c;调试半天才发现jupyter内核没配…

MinerU环境部署全攻略:Conda+CUDA+Python3.10参数详解

MinerU环境部署全攻略&#xff1a;CondaCUDAPython3.10参数详解 1. 引言&#xff1a;为什么选择这款MinerU镜像&#xff1f; 你是否还在为PDF文档中复杂的排版头疼&#xff1f;多栏文字、嵌套表格、数学公式、插图混杂在一起&#xff0c;手动提取不仅耗时还容易出错。现在&am…

浅谈CPU中的SIMD

目录 1.简介 2.如何检查CPU是否支持SIMD 2.1.命令行快速查询&#xff08;手动检查&#xff09; 2.2.C 代码动态检测&#xff08;程序运行时判断&#xff09; 2.3.各自系统判断 3.C 中利用 SIMD 的方式 3.1.编译器自动向量化 3.2.SIMD Intrinsics 3.3.C 标准并行算法 …

Qwen3-4B推理性能瓶颈?GPU算力深度调优部署实战教程

Qwen3-4B推理性能瓶颈&#xff1f;GPU算力深度调优部署实战教程 1. 为什么你的Qwen3-4B跑不满算力&#xff1f; 你是不是也遇到过这种情况&#xff1a;明明用的是RTX 4090D&#xff0c;显存带宽拉满&#xff0c;CUDA核心数也不少&#xff0c;但部署Qwen3-4B-Instruct-2507时&…

用Qwen-Image-Layered处理老照片,逐层修复更精细

用Qwen-Image-Layered处理老照片&#xff0c;逐层修复更精细 你有没有这样的经历&#xff1a;翻出一张泛黄的老照片&#xff0c;想修复它&#xff0c;却发现划痕、褪色、模糊交织在一起&#xff0c;根本无从下手&#xff1f;传统修图工具要么整体调整&#xff0c;失真严重&…

OCR技术新突破|DeepSeek-OCR-WEBUI多场景应用解析

OCR技术新突破&#xff5c;DeepSeek-OCR-WEBUI多场景应用解析 1. OCR技术的现实挑战与DeepSeek-OCR-WEBUI的破局之道 你有没有遇到过这样的情况&#xff1a;一堆纸质发票、合同、身份证需要录入系统&#xff0c;手动打字不仅慢&#xff0c;还容易出错&#xff1f;或者扫描的P…

NewBie-image-Exp0.1 vs LlamaGen对比:开源动漫大模型生成质量与效率评测

NewBie-image-Exp0.1 vs LlamaGen对比&#xff1a;开源动漫大模型生成质量与效率评测 1. 引言&#xff1a;为什么我们需要对比这两款模型&#xff1f; 如果你正在寻找一款能稳定生成高质量动漫图像的开源模型&#xff0c;那么你很可能已经听说过 NewBie-image-Exp0.1 和 Llam…

Z-Image-Turbo部署教程:SSH隧道映射7860端口详细步骤

Z-Image-Turbo部署教程&#xff1a;SSH隧道映射7860端口详细步骤 Z-Image-Turbo是阿里巴巴通义实验室开源的高效AI图像生成模型&#xff0c;作为Z-Image的蒸馏版本&#xff0c;它在保持高质量输出的同时大幅提升了推理速度。该模型仅需8步即可生成照片级真实感图像&#xff0c…

AI中小企业落地指南:Qwen3-4B开源部署一文详解

AI中小企业落地指南&#xff1a;Qwen3-4B开源部署一文详解 1. Qwen3-4B-Instruct-2507 是什么&#xff1f;中小企业为何要关注它&#xff1f; 你可能已经听说过很多大模型&#xff0c;但真正适合中小企业低成本、高效率落地的并不多。今天我们要聊的 Qwen3-4B-Instruct-2507&…

下一代代码模型趋势:IQuest-Coder-V1训练范式解析

下一代代码模型趋势&#xff1a;IQuest-Coder-V1训练范式解析 1. 引言&#xff1a;当代码不再静态&#xff0c;智能如何演进&#xff1f; 你有没有想过&#xff0c;为什么大多数代码大模型在面对真实项目迭代时总是“力不从心”&#xff1f;它们能写函数、补全代码&#xff0…

YOLOv9镜像避坑指南:常见问题与解决方案

YOLOv9镜像避坑指南&#xff1a;常见问题与解决方案 YOLOv9发布后&#xff0c;不少开发者在首次使用官方训练与推理镜像时遭遇了“能启动、跑不通、训不出、结果错”的典型困境。这不是模型能力的问题&#xff0c;而是环境、路径、参数和认知偏差共同导致的工程断点。本文不讲…

Sambert会议纪要生成:语音转录+摘要全流程实战

Sambert会议纪要生成&#xff1a;语音转录摘要全流程实战 在日常工作中&#xff0c;会议记录是一项繁琐但必不可少的任务。传统方式依赖人工听写和整理&#xff0c;耗时耗力且容易遗漏关键信息。随着语音识别与自然语言处理技术的发展&#xff0c;我们完全可以借助AI实现从语音…

Sambert部署需要多少存储?10GB空间规划建议指南

Sambert部署需要多少存储&#xff1f;10GB空间规划建议指南 1. Sambert语音合成镜像简介与核心价值 你是不是也遇到过这种情况&#xff1a;想快速搭建一个中文语音合成服务&#xff0c;结果卡在环境依赖、模型下载和路径配置上&#xff0c;折腾半天还跑不起来&#xff1f;尤其…