我目前正在Qt项目中工作,但我还没有太多关于Qt的经验,因此每次我被卡住时,我都会不时编码一些测试我不明白的事情。
我一直在研究的最后一个测试代码是QNetworkRequest
包装器,用于存储网络请求,如下所示:
std::list<R> requests;
QNetworkRequest request(QUrl("http://awesome/web/api"));
requests.emplace_back(NetworkAccessManager.get(request), myCallback);
对象R
如下所示:
首次尝试
struct R
{
R(QNetworkRequest *const r, void (*cb)(QNetworkRequest *)) :
m_r(r),
m_cb(cb)
{
if (m_r)
{
// Error on line below
QObject::connect(m_r, &QNetworkReply::finished, this, &R::reply);
}
}
private:
void reply() { m_cb(m_r); }
QNetworkRequest *const m_r;
void (*m_cb)(QNetworkRequest *);
};
但我收到以下错误:
no matching function for call to 'QObject::connect(QNetworkRequest* const&, void (QNetworkReply::*)(), R* const, void (R::*)())'
QObject::connect(m_r, &QNetworkReply::finished, this, &R::reply);
我不明白为什么连接不正确,我很确定之前做过类似的连接。
起初我怀疑错误与R
不是QObject
的事实有关,所以我做了以下更改:
第二次尝试
struct R
: public QObject // <-- New!
{
Q_OBJECT // <-- New!
R(QNetworkRequest *const r, void (*cb)(QNetworkRequest *)) :
m_r(r),
m_cb(cb)
{
if (m_r)
{
// Error on line below
QObject::connect(m_r, &QNetworkReply::finished, this, &R::reply);
}
}
private:
void reply() { m_cb(m_r); }
QNetworkRequest *const m_r;
void (*m_cb)(QNetworkRequest *);
};
此更改会产生更多编译错误:
no matching function for call to 'R::connect(QNetworkRequest* const&, void (QNetworkReply::*)(), R* const, void (R::*)())'
QObject::connect(m_r, &QNetworkReply::finished, this, &R::reply);
invalid use of incomplete type 'struct QtPrivate::QEnableIf<false, QMetaObject::Connection>'
declaration of 'struct QtPrivate::QEnableIf<false, QMetaObject::Connection>'
template <bool B, typename T = void> struct QEnableIf;
所以我继续努力修复编译器错误(由于我缺乏Qt经验而非常盲目),我的下一个尝试是将方法R::reply()
转换为插槽:
第三次尝试
struct R
: public QObject
{
Q_OBJECT
R(QNetworkRequest *const r, void (*cb)(QNetworkRequest *)) :
m_r(r),
m_cb(cb)
{
if (m_r)
{
// Error on line below
QObject::connect(m_r, &QNetworkReply::finished, this, &R::reply);
}
}
private slots: // <-- New!
void reply() { m_cb(m_r); }
private:
QNetworkRequest *const m_r;
void (*m_cb)(QNetworkRequest *);
};
这根本不能解决问题,事实上,它产生与先前版本完全相同的错误。
所以我最后一次解决问题的方法是在connect
指令上使用Qt宏:
上次尝试
struct R
: public QObject
{
Q_OBJECT
R(QNetworkRequest *const r, void (*cb)(QNetworkRequest *)) :
m_r(r),
m_cb(cb)
{
if (m_r)
{
// Error on line below
QObject::connect(m_r, SIGNAL(finished()), this, SLOT(reply()));
}
}
private slots:
void reply() { m_cb(m_r); }
private:
QNetworkRequest *const m_r;
void (*m_cb)(QNetworkRequest *);
};
报告以下错误:
no matching function for call to 'R::connect(QNetworkRequest* const&, const char*, R* const, const char*)'
QObject::connect(m_r, SIGNAL(finished()), this, SLOT(reply()));
no type named 'Object' in 'struct QtPrivate::FunctionPointer<const char*>'
invalid use of incomplete type 'struct QtPrivate::QEnableIf<false, QMetaObject::Connection>'
最后,我认为现在是停止猜测并开始寻求帮助的时候了:
connect
签名使用const char*
时,宏SIGNAL
和SLOT
正在将代码转换为字符?提前致谢。
答案 0 :(得分:3)
您必须使用QNetworkAccessManager
,因为它与QNetworkRequest
不同,继承自QObject
并且有finished
信号,因此您可以连接到它。< / p>
但要回答你的第一个问题:
您必须使用Q_OBJECT
宏并继承QObject
才能使用信号和插槽机制。
避免类似问题的指南:
QNetworkRequest
的文档没有说明有关finished
广告位的任何内容,也没有说明为了使用信号和插槽而必须继承QObject
。
答案 1 :(得分:1)
您正在尝试连接来自不相关类QNetworkReply
的对象的类QNetworkRequest
的信号。
此外,QNetworkRequest
不会继承QObject
。
为什么在上一次尝试
connect
签名使用const char*
时,宏SIGNAL
和SLOT
正在将代码转换为字符?
是的,SIGNAL
和SLOT
宏扩展为C风格的字符串。
答案 2 :(得分:0)
我遇到了同样的问题,我在应用程序的其他地方找到了该解决方案,并且可以正常工作。
代替:
QObject::connect(m_r, &QNetworkReply::finished, this, &R::reply);
写:
QObject::connect(m_r, &QNetworkReply::finished, [=](){this->reply();});