模板泛化类如何卸载释放内存

CustomWidget::~CustomWidget() {for (size_t i = 0; i < buttonManager.registerItem.size(); ++i) {delete buttonManager.registerItem(exitButton);}
}
以上该怎么写删除对象操作,类如下:template <typename T>
class GenericManager {
public:using ConditionFunc = std::function<bool(const T&, const QPoint&)>;using ActionFunc = std::function<void(QPainter&, const T&, bool)>;GenericManager() {}void registerItem(T* item) {int count = items.count();qWarning("Inserting at index %d, current count: %d", count, count);items.insert(count, item);}void processItems(QPainter& bufferPainter, QMouseEvent* event, QWidget* widget, ConditionFunc conditionFunc, ActionFunc actionFunc) {QPoint cursorPos = event ? event->pos() : widget->mapFromGlobal(QCursor::pos());// 将 i 的类型改为 size_tfor (size_t i = 0; i < items.count(); ++i) {T* item = items.at(i);if (item) {qWarning("Inserting at index");bool shouldHighlight = conditionFunc(*item, cursorPos);actionFunc(bufferPainter, *item, shouldHighlight);}}}private:QPtrVector<T> items;
};

使用模板来泛化类,如何增加删除对象的处理,增加代码如下:

 // 提供一个公共方法来获取 items 的数量size_t getItemCount() const {return items.count();}// 提供一个公共方法来获取指定索引的元素T* getItemAt(size_t index) const {if (index < items.count()) {return items.at(index);}return nullptr;}

析构函数删除对象:

CustomWidget::~CustomWidget() {// 遍历 GenericManager 中的 items 并释放内存for (size_t i = 0; i < buttonManager.getItemCount(); ++i) {ButtonInfo* item = buttonManager.getItemAt(i);if (item) {delete item;}}
}

注意不能用T* item= buttonManager.getItemAt(i);这样, CustomWidget 的析构函数中正确释放内存

T 是未定义的标识符,因为 T 是 GenericManager 类模板的模板参数,在 CustomWidget 类的作用域内并没有这个类型定义。而在 CustomWidget 里使用的是 GenericManager<ButtonInfo>,所以应该明确使用 ButtonInfo* 来接收 getItemAt 方法返回的指针。

调用方式:

void CustomWidget::paintEvent(QPaintEvent *event) {bufferPixmap = QPixmap(size());//bufferPixmap.fill(Qt::transparent);QPainter bufferPainter(&bufferPixmap);// drawBackgroundAndBorder(bufferPainter);buttonManager.processItems(bufferPainter, nullptr, this, [](const ButtonInfo& button, const QPoint& cursorPos) {return button.rect.contains(cursorPos);},[this](QPainter& painter, const ButtonInfo& button, bool isHighlighted) { // 添加 this 到捕获列表QRect drawRect(button.rect.x(), button.rect.y(), button.rect.width(), button.rect.height());qWarning("Draw rect: (%d, %d, %d, %d)", drawRect.x(), drawRect.y(), drawRect.width(), drawRect.height());QImage img;img.loadFromData(isHighlighted ? button.highlight_png : button.normal_png,isHighlighted ? button.highlight_png_size : button.normal_png_size,"PNG");if (img.isNull()) {// 使用 qWarning 替代 qDebugqWarning("Failed to load image");}// 如果 Qt 版本支持,可以保留下面这行// painter.setRenderHint(QPainter::Antialiasing); this->simulateLinearGradient(painter, drawRect, QColor(15, 10, 60), QColor(7, 69, 111));painter.drawImage(drawRect, img);});QPainter painter(this);painter.drawPixmap(0, 0, bufferPixmap);
}

注意,可以随意设置条件和绘制内容,conditionFun本例是lambda表达式 return button.rect.contains(cursorPos);

绘制结果简单一句img.loadFromData(isHighlighted ? button.highlight_png : button.normal_png,
                             isHighlighted ? button.highlight_png_size : button.normal_png_size,
                             "PNG");

这样充分利用C++的新特性,代码变得简单清晰

 

在 C++ 的 Lambda 表达式中,方括号 [] 部分被称为捕获列表,它用于指定 Lambda 表达式可以访问哪些外部变量。捕获列表不同的写法有不同的作用,下面详细解释为什么在你的代码里一个 Lambda 用 [],另一个用 [this]

1. [] 捕获列表

[](const ButtonInfo& button, const QPoint& cursorPos) {return button.rect.contains(cursorPos);
}

这里使用 [] 表示该 Lambda 表达式不捕获任何外部变量。这个 Lambda 表达式作为 conditionFunc 传递给 buttonManager.processItems 方法,它只依赖于传入的参数 button 和 cursorPos,不需要访问外部作用域中的任何变量,所以捕获列表为空。它的功能仅仅是判断鼠标位置 cursorPos 是否在按钮的矩形区域 button.rect 内。

2. [this] 捕获列表

[this](QPainter& painter, const ButtonInfo& button, bool isHighlighted) {QRect drawRect(button.rect.x(), button.rect.y(), button.rect.width(), button.rect.height());qWarning("Draw rect: (%d, %d, %d, %d)", drawRect.x(), drawRect.y(), drawRect.width(), drawRect.height());QImage img;img.loadFromData(isHighlighted ? button.highlight_png : button.normal_png,isHighlighted ? button.highlight_png_size : button.normal_png_size,"PNG");if (img.isNull()) {qWarning("Failed to load image");}this->simulateLinearGradient(painter, drawRect, QColor(15, 10, 60), QColor(7, 69, 111));painter.drawImage(drawRect, img);
}

这里使用 [this] 表示该 Lambda 表达式捕获当前对象的指针 this。在这个 Lambda 表达式中,调用了 this->simulateLinearGradient 方法,这是当前对象 CustomWidget 的一个成员函数。为了能够访问当前对象的成员函数和成员变量,需要通过 this 指针,所以在捕获列表中指定 this。这样,Lambda 表达式就可以在其内部调用当前对象的方法和访问成员变量了。

总结

  • []:不捕获任何外部变量,Lambda 表达式只能使用其参数列表中的变量。
  • [this]:捕获当前对象的指针,Lambda 表达式可以访问当前对象的成员函数和成员变量。

通过合理使用捕获列表,可以让 Lambda 表达式根据需要访问外部作用域中的变量,从而实现更灵活的功能

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

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

相关文章

在Linux系统上安装.NET

测试系统&#xff1a;openKylin(开放麒麟) 1.确定系统和架构信息&#xff1a; 打开终端&#xff08;Ctrl Alt T&#xff09;&#xff0c;输入cat /etc/os-release查看系统版本相关信息。 输入uname -m查看系统架构。确保你的系统和架构符合.NET 的要求&#xff0c;如果架构…

28. 【.NET 8 实战--孢子记账--从单体到微服务】--简易报表--报表定时器与报表数据修正

这篇文章是《.NET 8 实战–孢子记账–从单体到微服务》系列专栏的《单体应用》专栏的最后一片和开发有关的文章。在这片文章中我们一起来实现一个数据统计的功能&#xff1a;报表数据汇总。这个功能为用户查看月度、年度、季度报表提供数据支持。 一、需求 数据统计方面&…

深入探索C++17的std::any:类型擦除与泛型编程的利器

文章目录 基本概念构建方式构造函数直接赋值std::make_anystd::in_place_type 访问值值转换引用转换指针转换 修改器emplaceresetswap 观察器has_valuetype 使用场景动态类型的API设计类型安全的容器简化类型擦除实现 性能考虑动态内存分配类型转换和异常处理 总结 在C17的标准…

物管系统赋能智慧物业管理提升服务质量与工作效率的新风潮

内容概要 在当今的物业管理领域&#xff0c;物管系统的崛起为智慧物业管理带来了新的机遇和挑战。这些先进的系统能够有效整合各类信息&#xff0c;促进数字化管理&#xff0c;从而提升服务质量和工作效率。通过物管系统&#xff0c;物业管理者可以实时查看和分析各种数据&…

代码随想录算法训练营第三十八天-动态规划-完全背包-322. 零钱兑换

太难了 但听了前面再听这道题感觉递推公式也不是不难理解 动规五部曲 dp[j]代表装满容量为j&#xff08;也就是目标值&#xff09;的背包最少物品数量递推公式&#xff1a;dp[j] std::min(dp[j], dp[j - coins[i]] 1)当使用coins[i]这张纸币时&#xff0c;要向前找到容量为…

分组表格antd+ react +ts

import React from "react"; import { Table, Tag } from "antd"; import styles from "./index.less"; import GroupTag from "../Tag"; const GroupTable () > {const columns [{title: "姓名",dataIndex: "nam…

【JAVA实战】如何使用 Apache POI 在 Java 中写入 Excel 文件

大家好&#xff01;&#x1f31f; 在这篇文章中&#xff0c;我们将带你深入学习如何使用 Apache POI 在 Java 中编写 Excel 文件的技巧&#xff01;&#x1f4ca;&#x1f4da; 如果你是 Java 开发者&#xff0c;或者正在探索如何处理 Excel 文件的数据&#xff0c;那么这篇文章…

使用Avalonia UI实现DataGrid

1.Avalonia中的DataGrid的使用 DataGrid 是客户端 UI 中一个非常重要的控件。在 Avalonia 中&#xff0c;DataGrid 是一个独立的包 Avalonia.Controls.DataGrid&#xff0c;因此需要单独通过 NuGet 安装。接下来&#xff0c;将介绍如何安装和使用 DataGrid 控件。 2.安装 Dat…

Spring Bean实例化过程

Spring Bean 的生命周期管理是 Spring IOC 的核心功能之一。Bean 生命周期从实例化、依赖注入、初始化、销毁等各个阶段的源码分析,有助于深入理解 Spring 容器的工作原理,特别是在复杂应用中的应用和定制化。 本文将详细分析 Spring Bean 的生命周期,并通过源码分析每个阶…

C#分页思路:双列表数据组合返回设计思路

一、应用场景 需要分页查询&#xff08;并非全表查载入物理内存再筛选&#xff09;&#xff0c;返回列表1和列表2叠加的数据时 二、实现方式 列表1必查&#xff0c;列表2根据列表1的查询结果决定列表2的分页查询参数 三、示意图及其实现代码 1.示意图 黄色代表list1的数据&a…

【Linux】磁盘

没有被打开的文件 文件在磁盘中的存储 认识磁盘 磁盘的存储构成 磁盘的效率 与磁头运动频率有关。 磁盘的逻辑结构 把一面展开成线性。 通过扇区的下标编号可以推算出在磁盘的位置。 磁盘的寄存器 控制寄存器&#xff1a;负责告诉磁盘是读还是写。 数据寄存器&#xff1a;给…

waitpid使用

waitpid 是 Unix/Linux 系统中用于等待子进程状态变化的系统调用。它允许父进程挂起执行&#xff0c;直到指定的子进程终止或者发生了其他指定的状态变化。 waitpid 的语法 pid_t waitpid(pid_t pid, int *status, int options); pid: 要等待的子进程的进程 ID&#xff0c;特殊…

网站结构优化:加速搜索引擎收录的关键

本文来自&#xff1a;百万收录网 原文链接&#xff1a;https://www.baiwanshoulu.com/9.html 网站结构优化对于加速搜索引擎收录至关重要。以下是一些关键策略&#xff0c;旨在通过优化网站结构来提高搜索引擎的抓取效率和收录速度&#xff1a; 一、合理规划网站架构 采用扁…

第13章 深入volatile关键字(Java高并发编程详解:多线程与系统设计)

1.并发编程的三个重要特性 并发编程有三个至关重要的特性&#xff0c;分别是原子性、有序性和可见性 1.1 原子性 所谓原子性是指在一次的操作或者多次操作中&#xff0c;要么所有的操作全部都得到了执行并 且不会受到任何因素的干扰而中断&#xff0c;要么所有的操作都不执行…

记录 | Docker的windows版安装

目录 前言一、1.1 打开“启用或关闭Windows功能”1.2 安装“WSL”方式1&#xff1a;命令行下载方式2&#xff1a;离线包下载 二、Docker Desktop更新时间 前言 参考文章&#xff1a;Windows Subsystem for Linux——解决WSL更新速度慢的方案 参考视频&#xff1a;一个视频解决D…

PySide(PyQT)进行SQLite数据库编辑和前端展示的基本操作

以SQLite数据库为例&#xff0c;学习数据库的基本操作&#xff0c;使用QSql模块查询、编辑数据并在前端展示。 SQLite数据库的基础知识&#xff1a; https://blog.csdn.net/xulibo5828/category_12785993.html?fromshareblogcolumn&sharetypeblogcolumn&sharerId1278…

【算法学习笔记】36:中国剩余定理(Chinese Remainder Theorem)求解线性同余方程组

中国剩余定理 假定存在 m 1 . . m k m_1..m_k m1​..mk​两两互质&#xff0c;中国剩余定理旨在求解这样的线性同余方程组中的 x x x&#xff1a; x ≡ a 1 ( m o d m 1 ) x ≡ a 2 ( m o d m 2 ) . . . x ≡ a k ( m o d m k ) x \equiv a_1~(mod~m_1) \\ x \equiv a_2~(mod…

stack 和 queue容器的介绍和使用

1.stack的介绍 1.1stack容器的介绍 stack容器的基本特征和功能我们在数据结构篇就已经详细介绍了&#xff0c;还不了解的uu&#xff0c; 可以移步去看这篇博客哟&#xff1a; 数据结构-栈数据结构-队列 简单回顾一下&#xff0c;重要的概念其实就是后进先出&#xff0c;栈在…

JUC--ConcurrentHashMap底层原理

ConcurrentHashMap底层原理 ConcurrentHashMapJDK1.7底层结构线程安全底层具体实现 JDK1.8底层结构线程安全底层具体实现 总结JDK 1.7 和 JDK 1.8实现有什么不同&#xff1f;ConcurrentHashMap 中的 CAS 应用 ConcurrentHashMap ConcurrentHashMap 是一种线程安全的高效Map集合…

C++17 std::variant 详解:概念、用法和实现细节

文章目录 简介基本概念定义和使用std::variant与传统联合体union的区别 多类型值存储示例初始化修改判断variant中对应类型是否有值获取std::variant中的值获取当前使用的type在variant声明中的索引 访问std::variant中的值使用std::get使用std::get_if 错误处理和访问未初始化…