2013-03-07 62 views
2

我有一個自定義代理模型,偶爾會在新的列/行添加到其源模型時進行自檢。從文檔看來,在這種操作的開始和結束處調用QAbstractItemModel::beginResetModel()QAbstractItemModel::endResetModel()是正確的方法。不幸的是,我的檢修功能有幾個可能的退出點,我只知道我會忘記在每個退出點調用endResetModel,因爲它變得更加複雜。ModelResetter RAII對象

因此,我想創建一個簡單的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()在兩種protectedQAbstractItemModel。聲明ModelResetter作爲friend class在我的繼承模型似乎沒有幫助,因爲我試圖與基類交互。

我寧願不爲我實現的每個模型都做一個自定義的實現,所以我可以使用模板來做到這一點?我對模板語法還不是很熟悉。

編輯1:(我取出樣品模板代碼編輯2,以避免混淆)

這會是很好,如果我能以某種方式限制模板,只允許繼承QAbstractItemModel的類型,但我不在標準C++中看不到任何東西。我不會使用Boost。

編輯2:我想我並不是很清楚我的要求。在這裏,他們是:

  • 操作,並且在基類一般情況下
  • 強制執行,而在調試模式下QAbstractItemModel繼承需求而不受處罰在釋放模式
  • 使用簡單,幾乎沒有開銷
  • 不需要修改基類或新函數
+0

這與[此鏈接]基本相反(http://stackoverflow.com/questions/2767525/friendness-and-derived-class)。請注意,在基礎實現中'beginResetModel()'和'endResetModel()'不是'virtual',所以我不能利用它。 – Phlucious 2013-03-07 17:41:45

+1

也從'QAsbtractItemModel'繼承'ModelResetter':D – fasked 2013-03-07 18:33:49

+0

聰明,但是這並不違背'is-a'繼承思想的每一條規則嗎? – Phlucious 2013-03-07 20:03:08

回答

0

我不願意回答我自己的問題,但幾天後我整合了一個基於模板的解決方案來滿足我所有的要求。耶爲我的第一個從頭模板類。下面是執行:

//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 
} 

感謝您的幫助!

1

你可以讓你的繼承模型公開調用beginResetModel()和endResetModel()方法然後讓ModelResetter調用這些方法。

+0

那麼我是否沒有辦法編寫ModelResetter類,以便它使用qt模型基類的標準實現? – Phlucious 2013-03-08 16:57:12

+0

是繼承的模型嗎? – EHuhtala 2013-03-08 17:33:20

+0

是的。看到我上面的擴展示例代碼。 – Phlucious 2013-03-08 17:37:29