【问题标题】:ModelResetter RAII ObjectModelResetter RAII 对象
【发布时间】:2013-03-07 17:10:22
【问题描述】:

我有一个自定义代理模型,当将新列/行添加到其源模型中时,它偶尔会自行检修。从文档看来,在此类操作的开始和结束时调用QAbstractItemModel::beginResetModel()QAbstractItemModel::endResetModel() 是正确的方法。不幸的是,我的大修函数有几个可能的退出点,我只知道我会忘记在每个退出点调用endResetModel,因为它变得更加复杂。

因此,我想创建一个简单的 RAII 类,在构造时调用 beginResetModel,然后在销毁时调用 endResetModel,如下所示:

class ModelResetter
{
public:
    ModelResetter(QAbstractItemModel* model) : m_model(model)
    {
        m_model->beginResetModel();
    }
    ~ModelResetter()
    {
        m_model->endResetModel();
    }

private:
    QAbstractItemModel* m_model;
};

问题在于beginResetModel()endResetModel()QAbstractItemModel 中都是protected。在我的 inherited 模型中将 ModelResetter 声明为 friend class 似乎没有帮助,因为我正在尝试与基类进行交互。

我不想为我实现的每个模型都进行自定义实现,那么我可以使用模板来实现吗?我对模板语法还不是很熟悉。

编辑 1:(我删除了编辑 2 中的示例模板代码以避免混淆)

如果我能以某种方式将模板限制为只允许继承 QAbstractItemModel 的类型,那就太好了,但我在标准 C++ 中看不到任何允许这样做的东西。我不会使用 Boost。

编辑 2:我想我并不清楚我的要求。他们在这里:

  • 对一般情况的基类进行操作
  • 在调试模式下强制执行QAbstractItemModel 继承要求,而在发布模式下不受惩罚
  • 使用简单,几乎没有开销
  • 不需要修改基类或新函数

【问题讨论】:

  • 这与this link的情况基本相反。请注意,beginResetModel()endResetModel() 在基本实现中不是 virtual,所以我无法利用它。
  • 也从 QAsbtractItemModel 继承 ModelResetter :D
  • 聪明,但这不是几乎违反了is-a 继承概念的所有规则吗?
  • 也许你可以让你的 ModelResetter 在你的模型中成为一个嵌套类。然后你可以使用受保护的方法
  • 我正在考虑这个选项。不过,我更愿意写得更笼统。

标签: c++ qt templates qt4 qabstractitemmodel


【解决方案1】:

您可以让您继承的模型公开仅分别调用 beginResetModel() 和 endResetModel() 的方法,然后让 ModelResetter 调用这些方法。

【讨论】:

  • 那么我有没有办法编写ModelResetter类,使其使用qt模型基类的标准实现?
  • 您继承的模型是否公开继承?
  • pastebin.com/NFuHpB8c 是否为您编译?它对我有用。如果是这样,那么您似乎可以将 ModelResetter 设为 MyModel 的朋友,然后直接调用 beginResetModel()...您是否有错误消息表明它不起作用?
  • 是的,可以编译。但是,按照您的示例,我更愿意以更通用的方式实现class Op,以便它接受Base*,并且我可以将其应用于其他模型,而不仅仅是我目前实现的模型。
  • 你可以为 Base 制作一个包装器,其唯一目的是为 Op 导出所需的函数吗?然后让所有必需的 Derived 同级从该包装器扩展。
【解决方案2】:

我不想回答自己的问题,但几天后,我整理了一个基于模板的解决方案,可以满足我的所有要求。是的,我的第一个从头开始的模板类。这是实现:

//modelresetter.h
#include <QAbstractItemModel>

/* you must declare this class as a friend to your model
 * to give it access to protected members as follows:
 * template <class Model> friend class ModelResetter;
 */
template<class Model>
class ModelResetter
{
public:
    ModelResetter(Model* model) : m_model(model)
    {
        Q_ASSERT_X(qobject_cast<QAbstractItemModel*>(model) != 0, __FUNCTION__,
                   "templated object does not inherit QAbstractItemModel");
        m_model->beginResetModel();
    }
    ~ModelResetter()
    {
        m_model->endResetModel();
    }

private:
    Model* m_model;
};

及用法:

//mymodel.cpp
bool MyModel::overhaul()
{
    ModelResetter<MyModel> resetter(this); resetter;  //prevent compiler warning

    //do stuff
    if(somethingswrong)
        return false; //model will finish reset at every exit point

    //do more stuff
    return true; //model also completes reset on success
}

感谢您的帮助!

【讨论】:

    猜你喜欢
    • 2015-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-07
    相关资源
    最近更新 更多