關(guān)于Qt?C++中connect的幾種寫(xiě)法代碼示例
前言
這connect
函數(shù)就像是編程世界里的“茴”字,千變?nèi)f化,各有千秋。咱們程序員呢,就像是孔乙己那樣,雖然有時(shí)候會(huì)覺(jué)得這些變化有些好笑,甚至有些令人頭疼,但說(shuō)到底,還不是得乖乖地學(xué)著、用著,畢竟這可是編程里的“必備技能”。connect的編寫(xiě)每個(gè)人都有自己的習(xí)慣,也有其特點(diǎn),還是要深究一下的。
在Qt中,connect
函數(shù)用于將信號(hào)(signal)與槽(slot)連接起來(lái),以便在信號(hào)被發(fā)射時(shí)自動(dòng)調(diào)用槽函數(shù)。Qt提供了幾種不同的connect
寫(xiě)法,以及定義槽函數(shù)的方式,它們各有特點(diǎn)和適用場(chǎng)景。
1. 傳統(tǒng)的槽函數(shù)寫(xiě)法
在傳統(tǒng)的Qt項(xiàng)目中,槽函數(shù)通常是在類(lèi)的頭文件中使用slots:
關(guān)鍵字聲明的特殊成員函數(shù)。例如:
class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); private slots: // 使用slots關(guān)鍵字聲明槽函數(shù) void onCalculateClicked(); // ... 其他成員和槽函數(shù) ... };
然后在源文件中實(shí)現(xiàn)這個(gè)槽函數(shù):
void MainWindow::onCalculateClicked() { // 槽函數(shù)的實(shí)現(xiàn) }
使用這種寫(xiě)法時(shí),conect
函數(shù)通常這樣調(diào)用:
connect(pbt, SIGNAL(clicked()), this, SLOT(onCalculateClicked()));
這里使用的是SIGNAL()
和SLOT()宏
來(lái)將信號(hào)和槽轉(zhuǎn)換為字符串形式的標(biāo)識(shí)符。
2. 使用函數(shù)指針的connect寫(xiě)法(5.0)
在5.0及后續(xù)的Qt版本中,推薦使用函數(shù)指針的connect
寫(xiě)法,因?yàn)樗峁┝烁玫念?lèi)型檢查和編譯時(shí)錯(cuò)誤檢測(cè)。這種寫(xiě)法不需要使用slots:
關(guān)鍵字或SIGNAL()
/SLOT()
宏,而是直接使用函數(shù)指針。例如:
connect(pbt, &QPushButton::clicked, this, &MainWindow::onCalculateClicked);
在這種寫(xiě)法中,&QPushButton::clicked
是信號(hào)clicked
的函數(shù)指針,&MainWindow::onCalculateClicked
是槽函數(shù)的函數(shù)指針。編譯器會(huì)在編譯時(shí)檢查這些指針是否匹配。這種寫(xiě)法的優(yōu)點(diǎn)如下:
類(lèi)型安全:
函數(shù)指針的connect
寫(xiě)法提供了編譯時(shí)的類(lèi)型檢查。這意味著如果信號(hào)和槽的函數(shù)簽名不匹配,或者指定的函數(shù)不存在,編譯器會(huì)立即給出錯(cuò)誤提示。這大大減少了運(yùn)行時(shí)錯(cuò)誤的可能性,因?yàn)樗械倪B接都是在編譯時(shí)驗(yàn)證的。易于閱讀和維護(hù):
使用函數(shù)指針使得代碼更加直觀和易于理解。你可以直接看到哪個(gè)信號(hào)被連接到了哪個(gè)槽,而不需要通過(guò)字符串來(lái)間接表示。這有助于代碼的維護(hù)和調(diào)試,因?yàn)槟憧梢愿菀椎馗櫺盘?hào)和槽之間的連接關(guān)系。自動(dòng)處理函數(shù)重載:
當(dāng)存在多個(gè)重載的信號(hào)或槽函數(shù)時(shí),使用函數(shù)指針可以自動(dòng)選擇正確的重載版本。傳統(tǒng)的SIGNAL()
和SLOT()
宏在處理重載函數(shù)時(shí)可能會(huì)遇到問(wèn)題,因?yàn)樗鼈円蕾囉诤瘮?shù)名的字符串表示,無(wú)法區(qū)分重載的函數(shù)。而函數(shù)指針則包含了函數(shù)的完整簽名,因此可以準(zhǔn)確地選擇所需的函數(shù)。提高性能:
雖然性能差異可能不是非常顯著,但使用函數(shù)指針的connect
寫(xiě)法可能比使用字符串的宏稍微快一些。這是因?yàn)楹瘮?shù)指針可以直接在編譯時(shí)解析和連接,而不需要在運(yùn)行時(shí)進(jìn)行字符串比較和查找。與現(xiàn)代C++標(biāo)準(zhǔn)兼容:
隨著C++標(biāo)準(zhǔn)的不斷發(fā)展,使用函數(shù)指針的connect
寫(xiě)法更符合現(xiàn)代C++的編程風(fēng)格。它利用了C++11及更高版本中的特性,如lambda表達(dá)式和智能指針,使得Qt的代碼可以與這些現(xiàn)代特性更好地集成。減少宏的使用:
減少宏的使用可以降低代碼的復(fù)雜性和潛在的錯(cuò)誤。宏在C++中經(jīng)常是導(dǎo)致難以調(diào)試的問(wèn)題的源頭,因?yàn)樗鼈兪窃陬A(yù)處理階段展開(kāi)的,而不是在編譯階段進(jìn)行類(lèi)型檢查的。使用函數(shù)指針可以避免這些問(wèn)題。
3. Lambda表達(dá)式作為槽函數(shù)(C++11)
在C++11以后,除了傳統(tǒng)的槽函數(shù)和函數(shù)指針,Qt還支持使用Lambda表達(dá)式作為槽函數(shù)。這種寫(xiě)法非常靈活,因?yàn)樗试S你在connect
調(diào)用中直接編寫(xiě)槽函數(shù)的代碼,而不需要在類(lèi)中定義額外的成員函數(shù)。例如:
connect(pbt, &QPushButton::clicked, this, [this]() { // Lambda表達(dá)式作為槽函數(shù)的實(shí)現(xiàn) bool isOK; double r = lEdit->text().toDouble(&isOK); if (isOK && r >= 0) { lab2->setText(QString::number(AreaCircal(r))); } else { lab2->setText("請(qǐng)輸入合法的半徑!"); } });
這種寫(xiě)法的優(yōu)點(diǎn)如下:
捕獲或引用捕獲的方式來(lái)控制這些變量的生命周期和作用域。
靈活性和動(dòng)態(tài)性:
Lambda表達(dá)式提供了一種靈活的方式來(lái)定義槽函數(shù)的行為。你可以在connect
調(diào)用中直接編寫(xiě)Lambda表達(dá)式,而不需要事先在類(lèi)中聲明槽函數(shù)。這使得你可以根據(jù)需要在運(yùn)行時(shí)動(dòng)態(tài)地定義槽函數(shù)的行為。減少代碼量:
使用Lambda表達(dá)式作為槽函數(shù)可以減少需要編寫(xiě)的代碼量。你不需要為每個(gè)槽函數(shù)都聲明一個(gè)成員函數(shù),這不僅可以減少代碼量,還可以使代碼更加緊湊和易于管理。類(lèi)型安全:
與傳統(tǒng)的字符串宏相比,使用Lambda表達(dá)式作為槽函數(shù)提供了更好的類(lèi)型安全。編譯器會(huì)在編譯時(shí)檢查L(zhǎng)ambda表達(dá)式的類(lèi)型是否與信號(hào)的參數(shù)類(lèi)型匹配,從而避免了運(yùn)行時(shí)錯(cuò)誤。
除了第一種傳統(tǒng)寫(xiě)法外,現(xiàn)在較為流行的二、三種寫(xiě)法對(duì)比分析如下:
特性 | Lambda表達(dá)式 | 函數(shù)指針 |
---|---|---|
引入時(shí)間 | C++11 | C++早期版本、Qt5.0 |
定義方式 | 匿名函數(shù),直接在代碼中定義 | 需要顯式聲明和定義函數(shù),然后通過(guò)函數(shù)指針指向該函數(shù) |
語(yǔ)法簡(jiǎn)潔性 | 簡(jiǎn)潔,直接在調(diào)用處定義 | 相對(duì)繁瑣,需要額外的函數(shù)聲明和定義 |
類(lèi)型推斷 | 支持,編譯器可根據(jù)上下文推斷類(lèi)型 | 不支持,需要顯式指定函數(shù)返回類(lèi)型和參數(shù)類(lèi)型 |
捕獲外部變量 | 可以捕獲外部作用域中的變量 | 無(wú)法直接捕獲外部變量,只能訪問(wèn)函數(shù)參數(shù) |
執(zhí)行環(huán)境 | 在新的棧幀中執(zhí)行,具有獨(dú)立的調(diào)用環(huán)境和??臻g | 指向已存在的函數(shù),不擁有獨(dú)立的??臻g |
靈活性 | 適用于簡(jiǎn)單的、單行表達(dá)式的場(chǎng)合,易于在需要的時(shí)間和地點(diǎn)實(shí)現(xiàn)功能閉包 | 適用于調(diào)用已經(jīng)定義好的函數(shù),支持動(dòng)態(tài)綁定和回調(diào)函數(shù) |
代碼重用性 | 通常用于一次性或短暫的函數(shù)定義,代碼重用性較低 | 可以通過(guò)函數(shù)指針在不同位置調(diào)用同一函數(shù),代碼重用性較高 |
類(lèi)型安全性 | 類(lèi)型安全,編譯器檢查函數(shù)簽名 | 類(lèi)型安全性較低,容易出現(xiàn)類(lèi)型不匹配的問(wèn)題 |
性能 | 現(xiàn)代編譯器優(yōu)化后性能損失可忽略,但在某些情況下可能帶來(lái)輕微開(kāi)銷(xiāo) | 通常性能開(kāi)銷(xiāo)較低,但間接調(diào)用可能帶來(lái)一些額外開(kāi)銷(xiāo) |
使用場(chǎng)景 | 適用于需要定義簡(jiǎn)單匿名函數(shù)的場(chǎng)景,如STL算法中的排序和過(guò)濾 | 適用于需要?jiǎng)討B(tài)調(diào)用不同函數(shù)或?qū)崿F(xiàn)回調(diào)函數(shù)的場(chǎng)景,如事件處理、插件系統(tǒng)等 |
上述三種方法的特點(diǎn)和區(qū)別總結(jié):
- 傳統(tǒng)槽函數(shù):易于閱讀和維護(hù),特別是在槽函數(shù)邏輯復(fù)雜或需要多次重用的情況下。但是,它們?cè)黾恿祟?lèi)的復(fù)雜度,因?yàn)樾枰陬^文件中聲明槽函數(shù)。
- 函數(shù)指針的connect:提供了更好的類(lèi)型安全性,減少了運(yùn)行時(shí)錯(cuò)誤的可能性。它是現(xiàn)代Qt編程的推薦方式。
- Lambda表達(dá)式:非常靈活,適用于簡(jiǎn)單的、一次性的槽函數(shù)邏輯。但是,如果Lambda表達(dá)式過(guò)于復(fù)雜,可能會(huì)降低代碼的可讀性。
4.使用QOverload選擇重載信號(hào)的寫(xiě)法(Qt5.7)
使用QOverload
選擇重載信號(hào)的寫(xiě)法同樣是在Qt5引入的,在Qt框架中具有顯著的優(yōu)點(diǎn),并且適用于特定的場(chǎng)景。例如使用comboBox時(shí),有時(shí)使用索引,有時(shí)使用字符串作為參數(shù):
QComboBox *comboBox = new QComboBox; QLabel *label = new QLabel; label->setText("初始文本"); // 添加一些選項(xiàng)到組合框 comboBox->addItem("選項(xiàng) 1"); comboBox->addItem("選項(xiàng) 2"); comboBox->addItem("選項(xiàng) 3"); // 使用 QOverload 來(lái)連接重載的信號(hào)到不同的槽 QObject::connect(comboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), [](int index){ qDebug() << "當(dāng)前索引改變:" << index; }); QObject::connect(comboBox, QOverload<const QString&>::of(&QComboBox::currentIndexChanged), [](const QString &text){ qDebug() << "當(dāng)前文本改變:" << text; });
在這個(gè)例子中,currentIndexChanged
信號(hào)被重載了兩次:一次接受一個(gè)整型參數(shù)(表示當(dāng)前選中項(xiàng)的索引),另一次接受一個(gè)字符串參數(shù)(表示當(dāng)前選中項(xiàng)的文本)。我們使用QOverload
模板類(lèi)來(lái)指定我們想要連接的是哪一個(gè)重載版本的信號(hào)。然后,我們使用lambda表達(dá)式來(lái)定義當(dāng)信號(hào)發(fā)出時(shí)執(zhí)行的代碼。QOverload
是Qt 5.7及更高版本中引入的一個(gè)模板類(lèi),它用于在連接重載信號(hào)時(shí)提供類(lèi)型安全。在Qt 5.7之前的版本中,您可能需要使用static_cast
或函數(shù)指針來(lái)實(shí)現(xiàn)相同的功能,但這樣做通常不太安全且容易出錯(cuò)。
具體優(yōu)點(diǎn):
- 類(lèi)型安全:
- 使用
QOverload
可以確保在連接信號(hào)和槽時(shí),信號(hào)和槽的參數(shù)類(lèi)型完全匹配。這有助于在編譯時(shí)捕獲潛在的錯(cuò)誤,提高代碼的穩(wěn)定性。
- 使用
- 清晰明確:
- 通過(guò)顯式地指定要連接的重載信號(hào)版本,代碼更加清晰易懂。其他開(kāi)發(fā)者可以一目了然地看到信號(hào)和槽之間的對(duì)應(yīng)關(guān)系,減少誤解和錯(cuò)誤。
- 靈活性:
QOverload
允許開(kāi)發(fā)者在信號(hào)存在多個(gè)重載版本的情況下,選擇最適合當(dāng)前需求的信號(hào)版本進(jìn)行連接。這增加了代碼的靈活性,使其能夠適應(yīng)不同的場(chǎng)景和需求。
- 避免歧義:
- 在沒(méi)有
QOverload
之前,如果信號(hào)存在多個(gè)重載版本,開(kāi)發(fā)者需要通過(guò)其他方式(如函數(shù)指針轉(zhuǎn)換)來(lái)指定要連接的信號(hào)版本,這可能會(huì)引入歧義和錯(cuò)誤。而QOverload
提供了一種直接且明確的方式來(lái)避免這些問(wèn)題。
- 在沒(méi)有
這種寫(xiě)法用于當(dāng)信號(hào)存在多個(gè)重載版本時(shí),通過(guò)QOverload
模板類(lèi)明確指定要連接的是哪一個(gè)重載版本的信號(hào)。比如comboBox::currentIndexChanged
信號(hào)可能有多個(gè)重載版本,而通過(guò)使用QOverload<int>或QOverload<const QString&>
明確指定,然后進(jìn)行處理。適應(yīng)場(chǎng)景:
- 信號(hào)存在多個(gè)重載版本:
- 當(dāng)類(lèi)中的信號(hào)存在多個(gè)重載版本時(shí),使用
QOverload
可以明確指定要連接的重載信號(hào)版本,從而避免連接錯(cuò)誤或歧義。
- 當(dāng)類(lèi)中的信號(hào)存在多個(gè)重載版本時(shí),使用
- 需要類(lèi)型安全的信號(hào)槽連接:
- 在對(duì)類(lèi)型安全要求較高的項(xiàng)目中,使用
QOverload
可以確保信號(hào)和槽的參數(shù)類(lèi)型完全匹配,減少運(yùn)行時(shí)錯(cuò)誤的可能性。
- 在對(duì)類(lèi)型安全要求較高的項(xiàng)目中,使用
- 復(fù)雜的GUI應(yīng)用程序:
- 在復(fù)雜的GUI應(yīng)用程序中,信號(hào)和槽的連接可能變得非常復(fù)雜。使用
QOverload
可以使代碼更加清晰易懂,方便維護(hù)和管理。
- 在復(fù)雜的GUI應(yīng)用程序中,信號(hào)和槽的連接可能變得非常復(fù)雜。使用
- 需要靈活處理不同參數(shù)類(lèi)型的場(chǎng)景:
- 在某些場(chǎng)景下,可能需要根據(jù)不同的參數(shù)類(lèi)型來(lái)處理信號(hào)。使用
QOverload
可以方便地選擇不同參數(shù)類(lèi)型的信號(hào)版本進(jìn)行連接,從而滿足這些需求。
- 在某些場(chǎng)景下,可能需要根據(jù)不同的參數(shù)類(lèi)型來(lái)處理信號(hào)。使用
寫(xiě)到這里,感覺(jué)有點(diǎn)與孔乙己說(shuō)的茴字的幾種寫(xiě)法行為相仿,這里Qt里的connect
函數(shù),簡(jiǎn)直就是編程界的“茴”字啊!孔乙己要是穿越到編程世界,看到connect
的種種寫(xiě)法,怕是要笑得胡子都抖掉了,心里還得嘀咕:“這信號(hào)槽的connect,怎地也有如此多般變化,真是絕了!”
想象一下,咱們這connect
函數(shù),簡(jiǎn)直就是編程里的“百搭小能手”,既能跟老式的函數(shù)指針眉來(lái)眼去,又能跟新潮的Lambda表達(dá)式暗送秋波,還能跟那信號(hào)映射機(jī)制搞點(diǎn)小曖昧。這不,就像孔乙己研究“茴”字的幾種寫(xiě)法一樣,咱們程序員也得琢磨琢磨connect
的幾種姿勢(shì)-_-||b
在選擇哪種寫(xiě)法時(shí),應(yīng)根據(jù)具體的需求和代碼風(fēng)格來(lái)決定。對(duì)于復(fù)雜的槽函數(shù)邏輯,傳統(tǒng)的槽函數(shù)可能更合適;對(duì)于簡(jiǎn)單的邏輯或臨時(shí)的連接,Lambda表達(dá)式可能更方便;而函數(shù)指針的connect
則通常是一個(gè)折中的選擇,既安全又易于使用。
總結(jié)
到此這篇關(guān)于關(guān)于Qt C++中connect的幾種寫(xiě)法的文章就介紹到這了,更多相關(guān)Qt C++中connect寫(xiě)法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
c語(yǔ)言如何實(shí)現(xiàn)兩數(shù)之和
這篇文章主要介紹了c語(yǔ)言如何實(shí)現(xiàn)兩數(shù)之和,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07Qt音視頻開(kāi)發(fā)之利用ffmpeg實(shí)現(xiàn)倍速播放
這篇文章主要為大家詳細(xì)介紹了在Qt音視頻開(kāi)發(fā)中如何利用ffmpeg實(shí)現(xiàn)倍速播放功能(半倍速/2倍速/4倍速/8倍速),感興趣的小伙伴可以了解一下2022-11-11C++ 關(guān)于MFC List Control 控件的總結(jié)
這篇文章主要介紹了C++ 關(guān)于MFC List Control 控件的總結(jié)的相關(guān)資料,十分的詳細(xì),有需要的朋友可以參考下2015-06-06Linux搭建C++開(kāi)發(fā)調(diào)試環(huán)境的方法步驟
這篇文章主要介紹了Linux搭建C++開(kāi)發(fā)調(diào)試環(huán)境的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10