【问题标题】:C++ type's destructor not called in QMLQML 中未调用 C++ 类型的析构函数
【发布时间】:2013-09-06 23:56:36
【问题描述】:

我创建了一个 Sailfish 应用(使用最新的 Sailfish SDK)。我在将 C++ 对象暴露给 QML 时遇到问题。它继承了QSettings,

class Settings : public QSettings
{
    Q_OBJECT
    /**/
public:
    explicit Settings() : QSettings("Marcin Mielniczuk", "BigText") {}
    ~Settings() { qDebug() << "Dying"; }

    /**/
};

我注意到根本没有调用析构函数。 (没有析构函数输出)

我这样创建对象:

import QtQuick 2.0
import Sailfish.Silica 1.0
import BigText 1.0
import "pages"

ApplicationWindow
{
    initialPage: MainPage { }
    Settings {id: settings}
}

我的 main.cpp 是:

Q_DECL_EXPORT int main(int argc, char *argv[])
{
    QScopedPointer<QGuiApplication> app(Sailfish::createApplication(argc, argv));

    qmlRegisterType<Settings>("BigText", 1, 0, "Settings");

    QScopedPointer<QQuickView> view(Sailfish::createView("main.qml"));

    Sailfish::showView(view.data());

    return app->exec();
}

我做错了什么?

/edit: 未打印的文本不是实际问题——它只是问题的一个指标。析构函数中的 QSettings 同步也不起作用。

EDIT2:请注意,我使用的是 Sailfish Silica 中的 ApplicationWindow,而不是 QtQuick.Controls,并且窗口显示正常。这些组件必须与库存的 qt 快速组件有所不同。

【问题讨论】:

  • QSettings的析构函数是虚拟的吗?
  • 将 qDebug 更改为 std::cout,我认为,qDebug 可能正在使用事件循环...
  • 没有成功,但无论如何也无法解决问题 - 在析构函数中同步 QSettings 也无法正常工作...(即使没有显式析构函数)
  • doctorlove:是的,QSettings继承自QObject,其析构函数是virtual。
  • 嗯,确实没有错。看看我的回复。

标签: c++ qt qml destructor qt5


【解决方案1】:

您的逻辑本身并没有错。这是它的简化版本。我可以在本地运行它,并且每次关闭窗口并且应用程序终止时始终在输出上收到 Dying 消息。

如果您无法弄清楚,我建议将此代码转换为您正在执行的操作,直到它失败为止。

顺便说一句,这肯定只是你正在做的更大事情的 sn-p,但至少就示例而言,这些作用域指针并没有做太多事情。

ma​​in.qml

import QtQuick 2.0
import BigText 1.0

Item {
    width: 300; height: 300
    Settings {id: settings}
}

ma​​in.cpp

class Settings : public QSettings
{
    Q_OBJECT
    public:
    Settings() : QSettings("Marcin Mielniczuk", "BigText") {}
    ~Settings() { qDebug() << "Dying"; }

};

int main(int argc, char *argv[])
{
    QScopedPointer<QGuiApplication> app(new QGuiApplication(argc, argv));
    qmlRegisterType<Settings>("BigText", 1, 0, "Settings");
    QScopedPointer<QQuickView> view(new QQuickView());
    view->setSource(QUrl::fromLocalFile("main.qml"));
    view->show();
    return app->exec();
}

【讨论】:

  • 当我这样做时它确实有效。但是,一旦我将 Item 更改为 ApplicationWindow,它就停止了工作......
  • 它永远不会起作用,因为您不能将QQuickViewApplicationWindow 一起使用。它甚至没有加载主要组件。
  • 在 Sailfish SDK 中有 Qt 5.0.2(即,如发行说明中所写的“几乎 5.1”)。该应用程序的其余部分工作正常。该引擎由 Sailfish::create 创建。它的定义如下:github.com/owncloud/News-Qt-App/blob/master/sailfishapplication/…
【解决方案2】:

您可以尝试放置和标识您的应用程序窗口,并在某个时间明确使用 destroy() 方法,看看会发生什么。

【讨论】:

  • ApplicationWindow 是不可破坏的。我可以手动销毁设置,它工作正常。
【解决方案3】:

您不能将QQuickViewApplicationWindow 类一起使用。不仅没有调用您的析构函数,而且您的构造函数也不是,因为加载永远不会成功。

下面的代码在 Qt 5.1.1 下运行良好。在 OS X 10.8 和 Windows 7 上测试。

ma​​in.qrc

<RCC>
  <qresource prefix="/">
    <file>main.qml</file>
  </qresource>
</RCC>

ma​​in.pro

QT       += core gui qml quick
TARGET = qml-appwin-end-18597527
TEMPLATE = app
SOURCES += main.cpp
OTHER_FILES += main.qml
RESOURCES += main.qrc

ma​​in.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QSettings>
#include <QQuickWindow>
#include <QtQml>
#include <QDebug>

class Settings : public QSettings
{
    Q_OBJECT
    public:
    Settings() : QSettings("Marcin Mielniczuk", "BigText") {}
    ~Settings() { qDebug() << "Dying"; }
};

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    QQmlApplicationEngine engine;
    qmlRegisterType<Settings>("BigText", 1, 0, "Settings");
    engine.load(QUrl("qrc:/main.qml"));
    QObject *topLevel = engine.rootObjects().value(0);
    QQuickWindow *window = qobject_cast<QQuickWindow *>(topLevel);
    window->show();
    return app.exec();
}

#include "main.moc"

ma​​in.qml

import QtQuick 2.0
import QtQuick.Controls 1.0
import BigText 1.0

ApplicationWindow {
    width: 300; height: 300
    Settings {id: settings}
}

【讨论】:

  • 看起来 ApplicationWindow 是 Sailfish Silica 有点不同,因为它除了破坏子对象外还可以。加载窗口成功
【解决方案4】:

我的代码没有问题。这与 SDK 有关。调试展示

ASSERT: "QThread::currentThread() == QCoreApplication::instance()->thread()" in file debugger/qqmldebugserver.cpp, line 576

然后程序被中止,因此不调用析构函数。

【讨论】:

    猜你喜欢
    • 2017-04-28
    • 2021-05-18
    • 1970-01-01
    • 2019-11-09
    • 1970-01-01
    • 1970-01-01
    • 2015-08-22
    • 2019-08-08
    • 2013-09-19
    相关资源
    最近更新 更多