[Interest] Dangling QSqlTableModel Pointer

Scott Aron Bloom scott at towel42.com
Fri Mar 11 22:28:08 CET 2016


If you are relying on the parent/child relationship for your memory management, then you will be clear as long as your “parentObject” has not been deleted.

However, if you need your model to live longer than the object, I would use a std::shared_ptr and pass that around.

Scott

From: Interest [mailto:interest-bounces+scott=towel42.com at qt-project.org] On Behalf Of Hao Hu
Sent: Friday, March 11, 2016 11:16 AM
To: interest at qt-project.org
Subject: [Interest] Dangling QSqlTableModel Pointer

Hi All,

When using QSqlTableModel and the QTableView, the API provided (by the documentation<http://doc.qt.io/qt-5/qsqltablemodel.html>) is:


    QSqlTableModel<http://doc.qt.io/qt-5/qsqltablemodel.html#QSqlTableModel> *model = new QSqlTableModel<http://doc.qt.io/qt-5/qsqltablemodel.html#QSqlTableModel>(parentObject, database);

    model->setTable("employee");

    model->setEditStrategy(QSqlTableModel<http://doc.qt.io/qt-5/qsqltablemodel.html#QSqlTableModel>::OnManualSubmit);

    model->select();

    model->setHeaderData(0, Qt<http://doc.qt.io/qt-5/qt.html>::Horizontal, tr("Name"));

    model->setHeaderData(1, Qt<http://doc.qt.io/qt-5/qt.html>::Horizontal, tr("Salary"));



    QTableView<http://doc.qt.io/qt-5/qtableview.html> *view = new QTableView<http://doc.qt.io/qt-5/qtableview.html>;

    view->setModel(model);

    view->hideColumn(0); // don't show the ID

    view->show();

But most of the time, I'll need to manipulate the data in the database connected to the QSqlTableModel. Which means I need to pass the raw pointer "model" around to different classes. For instance, I defined a class Foo which has a data member that is a pointer of type QSqlTableModel *:


class Foo {



public:



    virtual void update();  // read up-to-date data from the database



protected:



    QSqlTableModel *m_model;  // it would be better to have QSharedPointer<QSqlTableModel> ?

}

So the reason for the Foo class to have a data member of type QSqlTableModel is to read the up-to-date data from the data from the database. However, this doesn't look good to me to have a raw pointer passed around like this. Obviously I won't let my virtual destructor of Foo to destruct this object pointed by "m_model" because it may be needed somewhere else. And also, it would be hard to manage the memory since Foo has no knowledge of whether the pointer is freed somewhere else.

So, instead of writing code like this, I changed the data member "m_model"'s type to QSharedPointer<QSqlTableModel> and when creating the object in the top level, I also wrapped the raw pointer with QSharedPointer. Basically it looks like this:


int main(int argc, char *argv[])

{

    /* create and open database "db" */



    if (db.open()) {

        ...

        QSharedPointer<QSqlTableModel> pModel = QSharedPointer<QSqlTableModel>(new QSqlTableModel(NULL, db) );

        Foo foo(pModel);

        ...



        tableView->setModel(pModel);   // The problem is here

    }

}

It's so disappointing when I saw the compiler was complaining about no corresponding member functions for QTableView to accept the QSharedPointer that points to the QSqlTableModel.

I'm just wondering why the QSqlTableModel is designed to be used like this way? Wouldn't it be better to use a smart pointer here instead of using the raw? If so, is it possible to add new member functions in the future that will accept the QSharedPointer<QSqlTableModel> as the input argument type?


Thank you for your help!


Regards,
Hao
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20160311/b86f3ba4/attachment.html>


More information about the Interest mailing list