代码之家  ›  专栏  ›  技术社区  ›  vico

创建QGenericArgument

  •  0
  • vico  · 技术社区  · 7 年前

    具有简单的测试应用程序 QMetaObject::invokeMethod 目的:

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    void MainWindow::setText( int value)
    {
        QString s = QString::number(value);
        ui->textEdit->setText(s);
    }
    
    
    
    
    
    void MainWindow::on_pushButton_clicked()
    {
        QGenericArgument genericArg =  Q_ARG(int, 321);
        bool inv = QMetaObject::invokeMethod( this,"setText",Qt::QueuedConnection, genericArg);
        qDebug("inv = %d\n", inv);
    }
    

    我得到了 0 在里面 setText 值。在哪里? 321 不见了?

    2 回复  |  直到 7 年前
        1
  •  1
  •   MSalters    7 年前

    从文件中 QGenericArgument :“此类不应直接使用。”.

    事实上,这个问题是通过遵循手册来解决的:

    void MainWindow::on_pushButton_clicked()
    {
        bool inv = QMetaObject::invokeMethod( this,"setText",
            Qt::QueuedConnection, Q_ARG(int, 321));
        qDebug("inv = %d\n", inv);
    }
    

    要理解为什么这是正确的,而您的代码不正确,请参阅豪伦的答案,但一般来说,您应该遵循手册。

        2
  •  3
  •   hauron    7 年前

    让我们看看引擎盖下面发生了什么。

    似乎整数321被视为(const)ref https://doc.qt.io/qt-5/qmetaobject.html#Q_ARG :

    QGenericArgument Q_ARG(Type, Type &value)
    QGenericArgument Q_ARG(Type, const Type &value)
    

    Q_ARG 只是一个宏:

    #define Q_ARG(type, data) QArgument<type >(#type, data)
    

    …返回类的对象 QArugment :

    template <class T>
    class QArgument: public QGenericArgument
    {
    public:
        inline QArgument(const char *aName, const T &aData)
            : QGenericArgument(aName, static_cast<const void *>(&aData))
            {}
    };
    

    …这反过来又是基于 QGenericArgument :

    class Q_CORE_EXPORT QGenericArgument
    {
    public:
        inline QGenericArgument(const char *aName = Q_NULLPTR, const void *aData = Q_NULLPTR)
            : _data(aData), _name(aName) {}
        inline void *data() const { return const_cast<void *>(_data); }
        inline const char *name() const { return _name; }
    
    private:
        const void *_data;
        const char *_name;
    };
    

    整个链只包含指向数据的常量指针,因此,安全的赌注是问题将是对临时的悬空引用。

    由于数据321只是一个临时数据,因此它首先绑定到常量引用,当 奇亚格 被解析为一个构造函数,这是可以的。

    但是,根据CPP标准参考解释: https://en.cppreference.com/w/cpp/language/reference_initialization#Lifetime_of_a_temporary 问题似乎是由以下原因引起的:

    每当引用绑定到临时对象或子对象时 因此,临时工的寿命延长到与 参考寿命,包括以下内容 例外 :

    (……)

    临时绑定到构造函数初始值设定项中的引用成员 列表仅在构造函数退出之前保持,而不是在 对象存在。(注:从dr 1696开始,这种初始化格式不正确)

    如果我的解释正确(不确定 pointer == reference 在这种情况下),则程序处于快乐的未定义行为状态(qt在运行时需要取消对悬空指针/ref的引用) invokeMethod )。

    因为它不会崩溃并使用一个0值(您怎么知道它是被调用的呢?你调试过了吗?)可能是您的构建配置隐藏了问题。