Использование std :: unique_ptr в Qt - PullRequest
0 голосов
/ 07 января 2020

Я так долго программировал на старом C ++, так как я и моя команда никогда не решали перейти на современные методы программирования (я признаю, что в этом тоже была моя вина), поэтому в последнее время я изучаю C + +11, C ++ 14, C ++ 17, так что я могу освоить его, и первое, что я наткнулся, был std :: unique_ptr, который, на мой взгляд, удивителен, но я все еще не уверен в его использовании с Qt, потому что я читал это в Qt, если я создаю QObject, который является дочерним для другого QObject, если родительский объект удален, то дочерний также будет удален, и использование std :: unique_ptr может привести к двойному удалению. Так что мне было интересно, это правильно:

MainWindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QSqlQueryModel>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
    QSqlDatabase p_AppDB;
    QSqlQueryModel *p_QueryModel;
};
#endif // MAINWINDOW_H

MainWindow. cpp:

#include "MainWindow.h"
#include "ui_MainWindow.h"

#include "Dialog.h"

#include <QDebug>
#include <QSqlQuery>
#include <QSqlError>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    p_AppDB = QSqlDatabase::addDatabase("QSQLITE" , "test"); // Set Database connection driver + name
    p_AppDB.setDatabaseName("AppDB.db"); // Set SQLite database file name
    if(!p_AppDB.open()) // Open database and check if connection failed
    {
        qDebug() << "ERR: " << p_AppDB.lastError().text(); // Print out an error message
    }

    p_QueryModel = new QSqlQueryModel(this); // How do i avoid using 'new' here ?

    QSqlQuery _Query(QSqlDatabase::database("test")); // Create a new QSqlQuery
    _Query.prepare("SELECT * FROM Users"); // Prepare a simple query to select everything from the table 'user'
    if(!_Query.exec()) // Execute query and check if the execution failed
    {
        qDebug() << _Query.lastError().text(); // Print out an error message
        return; // Return if the execution failed
    }
    p_QueryModel->setQuery(_Query); // Set the QSqlQuery with its data to the QSqlQueryModel we created
    ui->View_TableView->setModel(p_QueryModel); // Set the QSqlQueryModel with its data to the TableView

    // TEST
    auto dlg = std::make_unique<Dialog>(); // Create a new Dialog
    dlg->exec(); // Execute (Display) the dialog
}

MainWindow::~MainWindow()
{
    p_AppDB.close(); // Close the database connection
    delete ui;
}

Как использовать std :: unique_ptr например, при создании QWidget или чего-то еще вместо старого: QWidget * w = new QWidget (this);

Я знаю, что могут быть некоторые ошибки, потому что я не программировал довольно давно, и сейчас я возвращаясь к C ++ и Qt снова, но я надеюсь, что если есть какие-то другие ошибки, на которые вы можете указать.

Спасибо

1 Ответ

3 голосов
/ 07 января 2020

Короткий ответ: вы не можете - схема владения родителем / потомком QWidget и умные указатели не совместимы. Вы правы, что попытка управлять ими с помощью смарт-указателей часто приводит к проблемам с двойным удалением.

В некоторых случаях вы можете сделать что-то вроде std::unique_ptr<QWidget> ptr(new QWidget);, и объект QWidget будет удален, когда unique_ptr выходит из области видимости, как и ожидалось - но большая часть функциональности в Qt основана на обходе дерева объектов, которое собирается, когда вы делаете различные QWidget дочерними для других QWidget , поэтому управление виджетом через смарт-указатель целесообразно только в том случае, если этот виджет никогда не должен быть дочерним по отношению к какому-либо другому виджету.

Итак: когда вы находитесь в Qt-land, делайте так, как это делает Qt API, и при необходимости используйте традиционный подход «родитель-ребенок».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...