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

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

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_t
        for (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 替代 qDebug
                    qWarning("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.kler.cn/a/523969.html

相关文章:

  • vue3中customRef的用法以及使用场景
  • .NET MAUI 入门学习指南
  • 【C语言】static关键字的三种用法
  • 【Go语言圣经】第五节:函数
  • 17 一个高并发的系统架构如何设计
  • 抠图神器,全离线使用,支持win和mac
  • 【反悔堆】【hard】力扣871. 最低加油次数
  • 最近遇到的一些 Android 小问题
  • 省级数字经济发展水平数据(2011-2022年)-社科数据
  • goframe 多语言国际化解决方案
  • 使用numpy自定义数据集 使用tensorflow框架实现逻辑回归并保存模型,然后保存模型后再加载模型进行预
  • 16届蓝桥杯寒假刷题营】第2期DAY5IOI赛
  • Direct2D 极速教程(1) —— 画图形
  • Linux 学习笔记__Day3
  • 零刻SER7接口及配置跑分
  • AI 浪潮席卷中国年,开启科技新春新纪元
  • 创作三载·福启新章2025
  • 解决 -bash rz:command not found
  • [权限提升] 操作系统权限介绍
  • 二叉树-堆(补充)
  • 动态规划DP 数字三角型模型 最低通行费用(题目详解+C++代码完整实现)
  • vue中onclick如何调用methods中的方法
  • Zookeeper(32) Zookeeper的版本号(version)是什么?
  • 【BUUCTF】[羊城杯 2020]Blackcat1
  • ultralytics 是什么?
  • STM32简介