C++ 创建QGenericArgument
使用简单的应用程序测试C++ 创建QGenericArgument,c++,qt,C++,Qt,使用简单的应用程序测试QMetaObject::invokeMethod目的: #include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); } MainWindow::~MainWindow() { d
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);
}
我在
setText
值中得到0
。321
到哪里去了?让我们看看引擎盖下面发生了什么
似乎整数321被视为(const)ref:
Q_ARG
只是一个宏:
#define Q_ARG(type, data) QArgument<type >(#type, data)
。。。这反过来又基于qgenericalargument
:
template <class T>
class QArgument: public QGenericArgument
{
public:
inline QArgument(const char *aName, const T &aData)
: QGenericArgument(aName, static_cast<const void *>(&aData))
{}
};
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;
};
class Q\u CORE\u导出qgenericalargument
{
公众:
内联qgenericalargument(const char*aName=Q_NULLPTR,const void*aData=Q_NULLPTR)
:_data(aData),_name(aName){}
内联void*data()常量{return const_cast(_data);}
内联常量char*name()常量{return\u name;}
私人:
const void*_数据;
常量字符*_名称;
};
整个链只包含指向数据的常量指针,因此安全的做法是,问题可能是对临时变量的悬空引用
由于数据321只是一个临时数据,所以当Q_ARG
解析为构造函数时,它首先绑定到const引用,这没关系
然而,根据CPP对本标准的参考解释:出现问题的原因似乎是:
每当引用绑定到临时对象或子对象时
因此,临时的生存期被延长以匹配
引用的生存期,包括以下异常情况:
(……)
临时绑定到构造函数初始值设定项中的引用成员
列表仅在构造函数退出之前持续存在,而不是在
对象存在。(注:截至1696年DR,此类初始化的格式不正确)
如果我的解释是正确的(不确定在本例中是否pointer==reference
),则程序处于愉快的未定义行为状态(运行invokeMethod
时,Qt需要取消对悬挂指针/ref的引用)
由于它不会崩溃并使用0值(你怎么知道它被调用了?你调试过了吗?),因此构建配置可能隐藏了问题。让我们看看引擎盖下发生了什么 似乎整数321被视为(const)ref:
Q_ARG
只是一个宏:
#define Q_ARG(type, data) QArgument<type >(#type, data)
。。。这反过来又基于qgenericalargument
:
template <class T>
class QArgument: public QGenericArgument
{
public:
inline QArgument(const char *aName, const T &aData)
: QGenericArgument(aName, static_cast<const void *>(&aData))
{}
};
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;
};
class Q\u CORE\u导出qgenericalargument
{
公众:
内联qgenericalargument(const char*aName=Q_NULLPTR,const void*aData=Q_NULLPTR)
:_data(aData),_name(aName){}
内联void*data()常量{return const_cast(_data);}
内联常量char*name()常量{return\u name;}
私人:
const void*_数据;
常量字符*_名称;
};
整个链只包含指向数据的常量指针,因此安全的做法是,问题可能是对临时变量的悬空引用
由于数据321只是一个临时数据,所以当Q_ARG
解析为构造函数时,它首先绑定到const引用,这没关系
然而,根据CPP对本标准的参考解释:出现问题的原因似乎是:
每当引用绑定到临时对象或子对象时
因此,临时的生存期被延长以匹配
引用的生存期,包括以下异常情况:
(……)
临时绑定到构造函数初始值设定项中的引用成员
列表仅在构造函数退出之前持续存在,而不是在
对象存在。(注:截至1696年DR,此类初始化的格式不正确)
如果我的解释是正确的(不确定在本例中是否pointer==reference
),则程序处于愉快的未定义行为状态(运行invokeMethod
时,Qt需要取消对悬挂指针/ref的引用)
因为它不会崩溃并且使用0值(你怎么知道它被调用了?你调试过吗?),所以你的构建配置隐藏了这个问题。来自
qgenericalargument
的文档:“这个类不应该被直接使用。”
事实上,问题是通过遵循手册解决的:
void MainWindow::on_pushButton_clicked()
{
bool inv = QMetaObject::invokeMethod( this,"setText",
Qt::QueuedConnection, Q_ARG(int, 321));
qDebug("inv = %d\n", inv);
}
要理解为什么这是正确的,而您的代码是不正确的,请参见hauron的答案,但一般来说,您应该遵循手册。来自
qgenericalargument
的文档:“决不能直接使用此类。”
事实上,问题是通过遵循手册解决的:
void MainWindow::on_pushButton_clicked()
{
bool inv = QMetaObject::invokeMethod( this,"setText",
Qt::QueuedConnection, Q_ARG(int, 321));
qDebug("inv = %d\n", inv);
}
要理解为什么这是正确的,而您的代码不是正确的,请参阅hauron的答案,但一般来说,您应该遵循手册。我在调试时从断点了解
0
。但是如何传递函数的参数呢?@vico既然您可以调试,我建议您在genericArg
上放置一块手表。将为invokeMethod
调用复制它。Qt可能会多次复制参数(不确定它们如何解析此函数调用)。另外,便宜的方法是尝试将整数定义为局部变量,看看这是否有帮助,因为您不再有danling参考。我在调试时从断点了解0
。但是如何传递函数的参数呢?@vico既然您可以调试,我建议您在genericArg
上放置一块手表。将为invokeMethod
调用复制它。Qt可能会多次复制参数(不确定它们如何解析此函数调用)。另外,便宜的方法是尝试将整数定义为局部变量,看看这是否有帮助,因为您不再有danling ref。请添加Qt版本和窗口声明。问题无法产生请添加Qt版本和窗口声明。这个问题是无法产生的