您好,登錄后才能下訂單哦!
這篇文章主要介紹“Qt signal函數使用類內部類型作為參數導致connect不成功的原因是什么”,在日常操作中,相信很多人在Qt signal函數使用類內部類型作為參數導致connect不成功的原因是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Qt signal函數使用類內部類型作為參數導致connect不成功的原因是什么”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
問題代碼:
sender.h
class Sender : public QObject { Q_OBJECT public: explicit Sender(QObject *parent = nullptr); enum eResult { kSuccess, kFail, }; signals: void loginResult(eResult result); void otherSignal(QString str); };
定義了兩個信號:
loginResult() 這個信號采用 eResult 作為參數,而 eResult 是 Sender 類內部定義的類型;
otherSignal() 作為參照,使用Qt所定義的類型的信號。
receiver.h
class Receiver : public QObject { Q_OBJECT public: explicit Receiver(QObject *parent = nullptr); signals: public slots: void onLoginResult(Sender::eResult result); void onOtherSignal(QString str); private: Sender *sender_; };
在 Receiver 中定義了兩個slot分別接收 Sender 的兩個信號。
在 Receiver 的構造函數中:
Receiver::Receiver(QObject *parent) : QObject(parent) , sender_(new Sender()) { connect(sender_, SIGNAL(loginResult(Sender::eResult)), this, SLOT(onLoginResult(Sender::eResult))); connect(sender_, SIGNAL(otherSignal(QString)), this, SLOT(onOtherSignal(QString))); }
結果在運行時報錯:
提示信號沒有連接上。
如果我們將 eResult 放到 Sender 類外面,則沒有這個問題。
這是為什么呢?
是不是只要是類內部的類型都會出錯?
為了排除是我們自定義的枚舉的原因,我們把自己定義的 eResult 改成 MyString,其它也對應改過來。
再試:
結果還是報錯:
這也證定了我的猜想。為是什么呢?
打開自動生成的 moc_sender.cpp 文件看看里面的內容:
如果我們再加一個signal:
moc_sender.cpp 中會發生什么樣的變化呢?
(1)字面量里多出兩個新的字面量。
(2)在 qt_meta_data_Sender 中也多出些新的描述:
可以看出,qt_meta_data_Sender 中可以描述出一個 QObject 類有哪些信號函數。每個信號函數的返回類型與參數各為什么。
從上可以看到,qt_meta_data_Sender 中記錄的信號自定義的參數類型idx指向的是 MyString。我們在 Receiver 中 connect() 使用的是 Sender::MyString。會不會是兩者對不上號導致的呢?
如果我們改成這樣:
把 Sender:: 前綴加上。
看看會不會成功了呢?結果沒有再報錯了。
我們再來看看 moc_sender.cpp 的變化:
猜想:
在下面的 connect() 代碼中:
SIGNAL() 宏把 預編譯成 "loginResult(Sender::MyString)" 的字符串。在執行時,就會拿著該字串去 Sender 對象中找信號名為 "loginResult" 參數個數只有一個,參數類型名為 "Sender::MyString" 的信號進行連接。
如果我們在 Sender 中將 loginResult 信號的參數類型寫成 MyString 而不是寫全 Sender::MyString,那么在 connect() 時,它就不能在 Sender 的 qt_meta_data_Sender 中找到這個信號,所以就失敗了。
如果我們還是采用原來的做法:
而在 connect() 的地方,直接寫 MyString,而不寫成 Sender::MyString,如下:
執行報錯:
說是不兼容的參數類型。
可能 connect() 函數在入口處,就對參數signal與slot的參數類型字串進行比較,如果不一致,那么就會認為錯誤。
那反過來,我們在 connect() 時將 slot 的參數寫成:
執行結果:
如果我們把 Receive::onLoginResult() 的參數類型改成 MyString 呢?
如下:
編譯通過,運行時 connect() 正常。
是不是它只認類型的名稱,不做類型推導呢?
我們大膽地做一個嘗試:
我們給 MyString 亂指定一個類型。
結果編譯通過,運行時 connect() 正常。
從本質上 MyString 就是 QString 的別名。
如果在 Receive 端使用 QString 替代 MyString 是不是就不能 connect() 成功了呢?
如下修改:
編譯正常,運行結果:
這個實驗足于證明,connect() 只管類型名稱的比效,完全不做任何的類型推導。
綜上結論:
在執行 QObject::connect() 時,它會對signal與slot參數的名稱進行對比,只有名稱完會一致的才能連接上,否會不失敗。
值得注意的是:它只管對類型的名稱進行比較,完全不會做任何的類型推導與類型檢查。
到此,關于“Qt signal函數使用類內部類型作為參數導致connect不成功的原因是什么”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。