?? templates.html
字號:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- /home/reggie/tmp/qt-3.0-reggie-5401/qt-win-commercial-3.0.5/doc/object.doc:544 -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<meta name="Translator" content="Cavendish">
<meta name="Qt zh_CN Documents Website" content="http://www.qiliang.net/qt">
<title>為什么Qt不用模板來實現(xiàn)信號和槽?</title>
<style type="text/css"><!--
h3.fn,span.fn { margin-left: 1cm; text-indent: -1cm; }
a:link { color: #004faf; text-decoration: none }
a:visited { color: #672967; text-decoration: none }
body { background: #ffffff; color: black; font-family: "Times New Roman" }
--></style>
</head>
<body>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr bgcolor="#E5E5E5">
<td valign=center>
<a href="index.html">
<font color="#004faf">主頁</font></a>
| <a href="classes.html">
<font color="#004faf">所有的類</font></a>
| <a href="mainclasses.html">
<font color="#004faf">主要的類</font></a>
| <a href="annotated.html">
<font color="#004faf">注釋的類</font></a>
| <a href="groups.html">
<font color="#004faf">分組的類</font></a>
| <a href="functions.html">
<font color="#004faf">函數(shù)</font></a>
</td>
<td align="right" valign="center"><img src="logo32.png" align="right" width="64" height="32" border="0"></td></tr></table>
<h1 align=center>為什么Qt不用模板來實現(xiàn)信號和槽?</h1>
<p> 一個簡單的答案是,當初Qt被設計的時候,因為各種各樣的編譯器的不充分,所以在多平臺應用程序中完全使用模板機制是不可能的。甚至今天,許多被廣泛使用的C++編譯器在使用高級模板的時候還是有問題的。例如,你不能安全地依靠部分模板的示例,這對一些不平常的問題領域是必要的。因此Qt中模板的用法不得不保守。記住Qt是一個多平臺的工具包,在Linux/g++平臺上的進步不一定能夠在其它情況下獲得改進。
<p> 那些在模板執(zhí)行上比較弱的編譯器終將得到改進。但是,即使我們所有的用戶以極好的模板支持接近一個完全現(xiàn)代的C++編譯器的標準,我們也不會放棄通過使用我們的<a href="metaobjects.html#meta-object">元對象</a>編譯器的基于字符串的途徑。這里是為什么這樣做的五個原因:
<p> <h3>1. 語法問題</h3>
<p> 語法不是糖:我們用來表達我們的運算法則的語法較大程度上影響我們的代碼的可讀性和可維護性。Qt中信號和槽所用的語法在實踐中被證明是非常成功的。這種語法是直觀的、容易使用的和容易讀的。人們在學習Qt時發(fā)現(xiàn)這種語法幫助他們理解和使用信號和槽的概念——而不管它們的高度抽象和通用的性質。此外,在類定義中信號聲明保證了信號就像被保護的C++成員函數(shù)一樣被保護。這幫助了程序員在剛開始的時候就獲得了他們的設計權力,而不用不得不考慮設計模式。
<p> <h3>2. 預編譯程序是好的</h3>
<p> Qt的<tt><a href="moc.html#moc">moc</a></tt>(元對象編譯器)提供了一種的方式除了那些編譯語言的工具。它可以生成任何一個標準的C++編譯器都能編譯的額外的C++代碼。<tt>元對象編譯器</tt>讀取C++源文件。如果它發(fā)現(xiàn)其中有一個或多個類的聲明中含有“Q_OBJECT”這個宏,它就會為這些類生成另外一個包含元對象代碼的C++源文件。這個由<tt>元對象編譯器</tt>生成的C++源文件必須和它的類實現(xiàn)一起編譯和連接(或者它也可以被<tt>#included</tt>到個類的源文件中)。有特色的是<tt>元對象編譯器</tt>不是用手工來調用的,它可以自動地被連編系統(tǒng)調用,所以它不需要程序員額外的付出努力。
<p> 這里有一些其它的預編譯程序,比如,<tt>rpc</tt>和<tt>idl</tt>,它們使程序或者對象能夠通過進程或者machine boundaries來進行通訊。預編譯程序的選擇是編寫編譯器,專有的語言或者使用對話框或向導這些圖形編程工具來生成晦澀的代碼。我們能使我們的客戶使用他們所喜歡的工具,而不是把他們鎖定在一個專有的C++編譯器或者一個特殊的集成開發(fā)環(huán)境。我們不強迫程序員把生成的代碼添加到源程序倉庫中,而是鼓勵他們把我們的工具加入到他們的連編系統(tǒng)中:更加干凈,更加安全和更加富有UNIX精神。
<p> <h3>3. 靈活性為王</h3>
<p> C++是一種標準化的、強大的和精心制作的多用途語言。它只是用來開發(fā)很多領域的軟件項目的一種語言,生成許多種應用程序,從整個操作系統(tǒng)、數(shù)據(jù)庫服務器和高性能的圖形應用程序到普通的桌面應用程序。C++成功的關鍵之一是它著重于最大效能和最小內存占用同時保持ANSI-C的的兼容性的可伸縮語言設計
<p> 在這些優(yōu)勢當中,也有一些不利方面。對于C++,當它用來構成基于組件的圖形用戶界面編程的時候,靜態(tài)的對象模型在使用Objective C途徑的動態(tài)消息機制方面是明顯的劣勢。對于一個高端數(shù)據(jù)庫服務器或者一個操作系統(tǒng)使用正確的圖形用戶界面前端工具的這一設計選擇不是必須的。使用<tt>元對象編譯器</tt>,我們可以把這一劣勢轉化為優(yōu)勢并且會加入當我們遇到安全的和有效的圖形用戶界面程序編程這一挑戰(zhàn)的時候所需要的靈活性。
<p> 我們的方法比你用模板所能做到的一切更好。比如,我們有對象屬性。并且我們可以重載信號和槽,當你在使用可以重載這一關鍵理念的語言進行程序設計的時候你會感到很自然。我們的信號只對一個類實例的大小增加了零個字節(jié),也就是說我們能在不破壞二進制程序的兼容性的同時加入新的信號。因為我們不像模板那樣過多地依靠內嵌,我們可以使得代碼變得更小。添加一個新的連接就是增加一個簡單地函數(shù)調用而不是一個復雜地模板函數(shù)。
<p> 另外一個好處就是我們可以在運行時探測對象的信號和槽。我們可以通過使用類型安全的名稱調用而不用我們知道我們要連接的對象的確切類型來建立連接。這在一個基于模板的解決方案中是不可能的。這種運行時的自我檢測擴充了一種新的功能,比如我們可以使用Qt設計器的XML格式的<tt>ui</tt>文件來生成和連接圖形用戶界面。
<p> <h3>4. 調用性能不是一切</h3>
<p> Qt的信號和槽的執(zhí)行沒有基于模板的解決方案那樣快。發(fā)射一個信號的時間大約和普通模板實現(xiàn)中的四個普通函數(shù)調用的時間差不多,Qt要求努力控制到和十個普通函數(shù)調用差不多。這也不必驚訝,因為Qt機制中包括了一個通用調度器,自我測量和基本的腳本化的能力。它不過分依賴內嵌和代碼擴展,并且它提供了運行時得無比安全性。Qt的迭代(iterator)是安全的而那些基于模板的更快的系統(tǒng)確不是。甚至在你發(fā)射一個信號到多個接收器的過程中,那些接收器可以被安全地刪除而不會導致你的程序崩潰。沒有了這種安全,你的程序在調試自由的內存讀或寫錯誤這種困難情況下最終會崩潰。
<p> 雖然如此,一個基于模板的解決方案不是能比使用信號和槽更加提高應用程序的性能嗎?雖然Qt通過一個信號調用槽的時候會增加一點時間開銷是真的,這個調用的開銷只占整個槽調用的開銷的很小比例。以上的情況都是基于Qt的信號和槽系統(tǒng)使用典型的空槽。一旦你在槽里面做任何有意義的事情時,比如一些簡單的字符串操作,調用的時間開銷就可以忽略不計了。Qt的系統(tǒng)非常的優(yōu)化了,以至于任何東西都要求操作符new或者delete(比如,字符串操作或者從一個模板容器插入/刪除一些東西)的時間開銷要比發(fā)射一個信號多的多。
<p> 另外:如果你在一個性能為關鍵的任務中的一個嚴緊的內部回路中使用信號和槽并且你認為這種連接是瓶頸的話,建議你使用標準的監(jiān)聽接口模式來替代信號和槽。當這種情況發(fā)生時,總之你也許只需要一個一對一的連接。比如,你有一個對象從網(wǎng)絡上下載數(shù)據(jù),你使用信號來說明所需要的數(shù)據(jù)已經(jīng)到達的這種設計是非常明智的。但是如果你需要向接收者一個字節(jié)一個字節(jié)地發(fā)送數(shù)據(jù),使用監(jiān)聽接口要比信號和槽好。
<p> <h3>5. 沒有限制</h3>
<p> 因為我們有<tt>元對象編譯器</tt>來處理信號和槽,我們可以向它添加一些其它模板不能做的但很有用的東西。在這之中,有我們利用生成的<tt>tr()</tt>函數(shù)進行作用域翻譯,和一個自我測量和擴展的運行時的類型信息的先進的屬性系統(tǒng)。屬性系統(tǒng)有一個獨一無二的優(yōu)勢:沒有一個強大的和自我測量的屬性系統(tǒng)——如果這不是不可能的——一個Qt設計器這樣的強大的和通用的用戶界面設計工具就很難被寫出來。
<p> 帶有<tt>元對象編譯器</tt>預處理器的C++從本質上給我們帶來對象的C的靈活性或一個Java的運行時環(huán)境,當保持C++的唯一特性和可伸縮的優(yōu)點。它使得Qt成為我們今天擁有的靈活和舒適的工具。
<p>
<!-- eof -->
<p><address><hr><div align=center>
<table width=100% cellspacing=0 border=0><tr>
<td>Copyright © 2002
<a href="http://www.trolltech.com">Trolltech</a>
<td><a href="http://www.trolltech.com/trademarks.html">Trademarks</a>
<td><a href="zh_CN.html">譯者:Cavendish</a>
<td align=right><div align=right>Qt 3.0.5版</div>
</table></div></address></body>
</html>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -