如何存储QPropertyChangeHandler实例?Qt属性变更处理编译报错解决
如何正确存储QProperty::onValueChanged返回的QPropertyChangeHandler对象
QProperty::onValueChanged()会返回一个QPropertyChangeHandler对象,这个对象必须存为成员变量——一旦它被销毁,关联的回调函数就会被自动注销。但QPropertyChangeHandler是带Functor模板参数的类,我不知道该指定什么类型,请问该怎么存储这个返回对象?
我的尝试代码
PropTest.h
#ifndef PROP_TEST #define PROP_TEST #include <QObject> #include <QProperty> #include <QString> #include <QPropertyChangeHandler> #include <functional> class PropTest : public QObject { Q_OBJECT public: QProperty<QString> m_property; PropTest(); ~PropTest() = default; QPropertyChangeHandler< std::function<void()> > propertyChangeHandler; void TestFunction(); }; #endif
PropTest.cpp
#include <QObject> #include <QString> #include <QDebug> #include <QApplication> #include "prop_test.h" PropTest::PropTest() { // <- 错误发生在此处 this->propertyChangeHandler = this->m_property.onValueChanged(&PropTest::TestFunction); } void PropTest::TestFunction() { // 后续处理 } int main(int arc, char* argv[]) { auto app = QApplication(arc, argv); auto ob = new PropTest{}; ob->m_property = "String"; ob->m_property = "New"; app.exec(); }
遇到的编译错误
[build] prop_test.cpp: In constructor 'PropTest::PropTest()': [build] prop_test.cpp:11:20: error: no matching function for call to 'QPropertyChangeHandler<std::function<void()> >::QPropertyChangeHandler()' [build] 11 | PropTest::PropTest() { [build] | ^
问题原因及解决方法
1. 错误根源
QPropertyChangeHandler没有默认构造函数。你在类里声明成员变量propertyChangeHandler时,编译器会自动尝试调用它的默认构造函数完成初始化,但这个类不支持默认构造,因此触发编译错误。
2. 正确的存储方式
不需要手动指定Functor模板参数,利用C++的类型推导就能解决问题,以下是两种可行方案:
方案一:用decltype推导类型+成员初始化列表
直接让编译器推导回调对应的QPropertyChangeHandler类型,然后在构造函数的初始化列表里完成创建:
修改后的PropTest.h
#ifndef PROP_TEST #define PROP_TEST #include <QObject> #include <QProperty> #include <QString> #include <QPropertyChangeHandler> class PropTest : public QObject { Q_OBJECT public: QProperty<QString> m_property; PropTest(); ~PropTest() = default; // 用decltype自动推导handler的类型 decltype(m_property.onValueChanged(&PropTest::TestFunction)) propertyChangeHandler; void TestFunction(); }; #endif
修改后的PropTest.cpp
#include <QDebug> #include <QApplication> #include "prop_test.h" // 在成员初始化列表里直接初始化handler PropTest::PropTest() : propertyChangeHandler(m_property.onValueChanged(&PropTest::TestFunction)) { } void PropTest::TestFunction() { qDebug() << "属性已变更:" << m_property.value(); } int main(int argc, char* argv[]) { QApplication app(argc, argv); PropTest ob; ob.m_property = "String"; ob.m_property = "New"; return app.exec(); }
方案二:用std::optional延迟初始化(适合带条件的场景)
如果需要根据某些条件决定是否创建回调,可以用std::optional包裹handler,延迟到构造函数体内初始化:
修改后的PropTest.h
#ifndef PROP_TEST #define PROP_TEST #include <QObject> #include <QProperty> #include <QString> #include <QPropertyChangeHandler> #include <optional> class PropTest : public QObject { Q_OBJECT public: QProperty<QString> m_property; PropTest(); ~PropTest() = default; // 用std::optional包裹,支持延迟初始化 std::optional<decltype(m_property.onValueChanged(&PropTest::TestFunction))> propertyChangeHandler; void TestFunction(); }; #endif
修改后的PropTest.cpp
#include <QDebug> #include <QApplication> #include "prop_test.h" PropTest::PropTest() { // 可添加条件判断,比如仅在满足特定条件时初始化 propertyChangeHandler.emplace(m_property.onValueChanged(&PropTest::TestFunction)); } void PropTest::TestFunction() { qDebug() << "属性已变更:" << m_property.value(); } int main(int argc, char* argv[]) { QApplication app(argc, argv); PropTest ob; ob.m_property = "String"; ob.m_property = "New"; return app.exec(); }
3. 关键说明
- QPropertyChangeHandler的模板参数由你传入的回调类型决定,不用手动写
std::function<void()>,用decltype推导可以避免类型不匹配的问题。 - 必须保证QPropertyChangeHandler的生命周期长于对应的QProperty,将其存为类成员刚好满足这个要求。
内容的提问来源于stack exchange,提问作者Eliazar
相关产品推荐
相关产品推荐

