C++后继有人——D语言
?D語言是什么? D語言是由Digital Mars公司開發(fā)的編程語言,起因是為了改進C++。它與C二進制兼容(不完全),可編譯為本地碼,有GC也可手動管理內(nèi)存,語法上借鑒多種語言,模板則在C++的基礎(chǔ)上做了相當(dāng)大的擴充。D 語言既有?C 語言的強大威力,又有?Python?和?Ruby?的開發(fā)效率。它是一種集垃圾回收、手工內(nèi)存操作、契約式設(shè)計、高級模板技術(shù)、內(nèi)嵌匯編、內(nèi)置單元測試、Mixin 風(fēng)格多繼承、類?Java包管理機制、內(nèi)置同步機制、內(nèi)建基本運行時信息的系統(tǒng)級編程語言。編輯本段D語言詳細介紹 D 語言是一種通用的系統(tǒng)和應(yīng)用編程語言。它是比 C++ 更高級的語言,同時還保持了生成高效代碼以及直接訪問操作系統(tǒng)API和硬件的能力。D很適合于編寫從中等規(guī)模到那些由團隊合作完成、數(shù)百萬行代碼規(guī)模的各種程序。D易于學(xué)習(xí),為編程者提供了很多便利,并且適用各種野心勃勃的編譯器優(yōu)化技術(shù)。?
D 不是腳本語言,也不是一種解釋型語言。它不需要虛擬機、宗教、或者高于一切的哲學(xué)。它是給實際的編程者使用的實際的語言,它幫助編程者快速、可靠的完成易于維護、易于理解的代碼。?
D 是數(shù)十年來實現(xiàn)多種語言編譯器的經(jīng)驗的積累,是用那些語言構(gòu)造大型工程的嘗試的積累。D 從那些語言(主要是 C++ )那里獲得了靈感,并使用經(jīng)驗和現(xiàn)實世界中的實用性來馴服它。?
為什么是 D ?
確實,為什么?有誰需要另一種編程語言??
自從 C 語言被發(fā)明以來,軟件工業(yè)走過了一段很長的路。許多新的概念被加入了 C++中,但同時維護了同 C 的向后兼容性,包括兼容了原始設(shè)計中的所有的弱點。有很多修正這些弱點的嘗試,但是兼容性是最大的困擾。同時,C 和 C++都在不斷引入新的特性。這些新特性必須被小心的加入到現(xiàn)有的結(jié)構(gòu)中,以免重寫舊的代碼。最終的結(jié)果十分復(fù)雜—— C 標(biāo)準(zhǔn)將近 500 頁,C++標(biāo)準(zhǔn)大概有 750 頁!C++ 實現(xiàn)起來既困難又代價高昂,造成的結(jié)果就是各種實現(xiàn)之間都有差別,因此很難寫出完全可以移植的 C++ 代碼。?
C++程序員傾向于使用語言中的孤島來編程,也就是說,他們傾向于十分精通語言中的某個特性而避免使用其他特性。盡管代碼通常在編譯器之間是可移植的,但在程序員之間移植就不那么容易了。C++ 的一個長處是它支持很多根本上不同的編程風(fēng)格——但從長遠來看,互相重復(fù)和互相沖突的風(fēng)格會給開發(fā)帶來妨礙。?
C++ 在標(biāo)準(zhǔn)庫而不是語言核心中實現(xiàn)了可改變大小的數(shù)組和字符串拼接等。不在語言核心中實現(xiàn)這些功能造成了幾種不太理想的結(jié)果。?
是否能把 C++ 的能力釋放、重新設(shè)計并重鑄到一門簡單、正交并實用的語言中呢? 這種語言是否能做到易于正確實現(xiàn),并使編譯器有能力有效地生成高度優(yōu)化的代碼呢??
現(xiàn)代編譯器技術(shù)已經(jīng)取得了很大的進步,有些原來用作原始編譯技術(shù)的補充的語言特性已經(jīng)可以被忽略了(一個這樣的例子是 C 語言中的‘register’關(guān)鍵字,一個更為微妙的例子是 C中的宏預(yù)處理程序)。我們可以依賴現(xiàn)代編譯器的優(yōu)化技術(shù)而不是使用語言特性(如同原始的編譯器所做的那樣)來獲得可以接受的代碼質(zhì)量。編輯本段D的主要目標(biāo) 通過加入已經(jīng)被證明的能夠提高生產(chǎn)力的特性、調(diào)整語言特性以避免常見但耗費精力的bug的出現(xiàn),至少減少軟件開發(fā)成本10%。?
是代碼易于在編譯器之間、在機器之間、在操作系統(tǒng)之間移植。?
支持多種編程范式,也就是至少支持命令式、結(jié)構(gòu)化、面向?qū)ο蠛头缎途幊谭妒健?
對于熟悉 C 或者 C++ 的人來說,學(xué)習(xí)曲線要短。?
提供必要的低級訪問能力。?
要使 D 的編譯器從根本上易于實現(xiàn)(相對于 C++ 來說)。?
要同本機的 C 語言應(yīng)用程序二進制接口相兼容。?
語法要做到上下文無關(guān)。?
對編寫國際化的應(yīng)用程序提供便利的支持。?
同時支持契約式編程和單元測試方法論。?
能夠構(gòu)建輕量級的、獨立的程序。
從C/C++保留而來的特征
粗看上去 D 就像 C 和 C++ 。這樣一來學(xué)習(xí)以及將代碼移植到 D 就很容易。從 C/C++ 轉(zhuǎn)向 D 應(yīng)該很自然。程序員不必從頭學(xué)起。?
使用 D 并不意味著程序員會如 Java 或者 Smalltalk那樣被嚴(yán)格的限制在某一個運行時 vm (虛擬機)上。D 沒有虛擬機,編譯器直接生成可連接的目標(biāo)文件。D 如同 C那樣被直接連接到操作系統(tǒng)。通常那些你熟悉的工具如 make 同樣適用于 D 的開發(fā)。?
D 將很大程度上保留 C/C++ 的 觀感 。它將使用相同的代數(shù)語法,絕大多數(shù)的相同表達式和語句形式,以及總體的結(jié)構(gòu)。?
D 程序既可以采用 C 風(fēng)格的 函數(shù)和數(shù)據(jù) 范式,也可以采用 C++ 風(fēng)格的 面向?qū)ο?范式,或者它們兩者的混合。?
編譯/鏈接/調(diào)試 的開發(fā)模型將會被繼承下來,但是把 D 編譯成為字節(jié)碼然后解釋執(zhí)行也不會有任何問題。?
異常處理 越來越多的使用經(jīng)驗顯示,異常處理是比 C 傳統(tǒng)的“出錯代碼/全局errno變量”模型更為高級的錯誤處理模型。?
運行時類型識別 C++ 部分地實現(xiàn)了這個功能,而 D 更進一步。對運行時類型識別的完全支持將使垃圾收集運行的更好,會使調(diào)試器的功能更強,會使對自動持久化的支持更好等等。?
D 維持了同 C 調(diào)用慣例 的兼容。這樣就能夠使 D 程序直接訪問操作系統(tǒng)的 API 。程序員有關(guān)現(xiàn)有 API 和編程范例的知識和經(jīng)驗可以繼續(xù)在使用 D 時使用而只需付出很少的努力。?
運算符重載 D 支持對運算符的重載,這樣就可以用用戶定義的類型擴展由基本類型構(gòu)成的類型系統(tǒng)。?
模板模板是實現(xiàn)范型編程的一種手段。其他的手段包括使用宏或者采用協(xié)變數(shù)據(jù)類型。使用宏已經(jīng)過時了。協(xié)變類型很直接,但是低效且缺少類型檢查。C++模板的問題是它們太復(fù)雜,同語言的語法不和諧,還有各種各樣的類型轉(zhuǎn)換和重載規(guī)則,等等。D 提供了一種簡單得多的使用模板的方法。?
RAII(資源獲得即初始化) RAII 技術(shù)是編寫可靠軟件的重要方法之一。?
Down and dirty 編程 D 將保留 down-and-dirty編程的能力,而不用采用別的語言編寫的外部模塊。在進行系統(tǒng)編程時,有時需要將一種指針轉(zhuǎn)換成另一種指針,或者使用匯編語言。D 的目標(biāo)不是避免down and dirty 編程,而是減少在進行普通程序設(shè)計時對它們的需要。?
廢棄的特征
對 C 的源碼級兼容性。保留對 C 的源碼級兼容的擴展已經(jīng)有了(C++ 和 Objective-C)。在這方面的進一步工作受制于大量的遺留代碼,已經(jīng)很難對這些代碼進行什么重大的改進了。?
對 C++ 的鏈接兼容性。C++ 的運行時對象模型太復(fù)雜了——如果要較好的支持它,基本上就是要求 D 編譯器變成一個完整的 C++ 編譯器了。?
C預(yù)處理程序。宏處理是一種擴展語言的簡單方法,它可以給語言加入某些語言本不支持的(對于符號調(diào)試器不可見的)特征。條件編譯、使用 #include分層的文本、宏、符號連接等,本質(zhì)上構(gòu)成了兩種難以區(qū)分兩種語言的融合體,而不是一種語言。更糟的是(或許是最好的),C預(yù)處理程序是一種十分原始的宏語言。是停下來的時候了,看看預(yù)處理程序是用來做什么的,并將這些功能直接設(shè)計到語言內(nèi)部。?
多重繼承。它是一種擁有飽受爭議的價值的復(fù)雜特征。它很難用一種高效的方式實現(xiàn),而且在編譯器實現(xiàn)它時很容易出現(xiàn)各種 bug 。幾乎所有的 MI 的功能都能夠通過使用單根繼承加接口和聚集的方式實現(xiàn)。而那些只有 MI 才能支持的功能并不能彌補它帶來的副作用。?
名字空間。當(dāng)鏈接獨立開發(fā)的代碼時,可能會發(fā)生名字的沖突,名字空間就是解決這個問題的一種嘗試。模塊的概念更簡單并且工作得更好。?
標(biāo)記名字空間。這是 C 的一個糟糕的特征,結(jié)構(gòu)的標(biāo)記名稱位于一個同其它符號不同的符號表中。C++ 試圖合并標(biāo)記名字空間和正常的名字空間,但同時還要維持對遺留 C 代碼的向后兼容性。造成的結(jié)果是不可打印。?
前向聲明。C 編譯器在語義上只知道什么東西實在詞法上位于當(dāng)前狀態(tài)之前的。C++進行了一點點擴展,類中的成員可以依賴于它之后聲明的類成員。D更進一步,得到了一個合情合理的結(jié)論,前向聲明根本就沒有存在的必要。函數(shù)可以按照一種自然的順序定義,不用再像 C那樣為了避免前向聲明而采用常用的從里到外的順序定義。?
包含文件。造成編譯器運行緩慢的原因之一是編譯每個編譯單元時都需要重新解析數(shù)量巨大的頭文件。包含文件的工作應(yīng)該采用導(dǎo)入到符號表中的方式來完成。?
在堆棧上創(chuàng)建對象實例。在 D 中,所有的類都通過引用來訪問。這樣就不需要復(fù)制構(gòu)造函數(shù)、賦值運算符、復(fù)雜的析構(gòu)語義以及同異常處理中的堆棧展開的相互作用。內(nèi)存資源由垃圾收集程序負責(zé)釋放,其他資源通過使用 D 的 RAII 特征釋放。?
三字節(jié)碼和雙字節(jié)碼。Unicode 是未來。?
預(yù)處理程序。現(xiàn)代語言不應(yīng)該需要文本處理,它們應(yīng)該只需要符號處理。?
非虛成員函數(shù)。在 C++中,由累得設(shè)計者決定一個函數(shù)是否應(yīng)該是虛函數(shù)。在子類中重寫一個函數(shù)而忘記在父類中將其更新為虛函數(shù)是一個常見的(并且非常難以發(fā)現(xiàn)的)編碼錯誤。將所有成員函數(shù)設(shè)置為虛函數(shù),并由編譯器來判斷函數(shù)是否被重寫、并由此將沒有被重寫的函數(shù)轉(zhuǎn)換為非虛函數(shù)的做法更為可靠。?
任意長度的位字段。位字段是一種復(fù)雜、低效并且很少用到的特征。?
支持16位計算機。D 從不考慮混合使用遠/近指針和其它所有用于聲稱好的16位代碼的機制。D 語言的設(shè)計假設(shè)目標(biāo)機器至少擁有32位的平坦內(nèi)存空間。D 將能夠被毫無困難的移植到64位架構(gòu)上。?
對編譯遍數(shù)的互相依賴。在 C++ 中,需要一個符號表和各種的預(yù)處理程序命令才能成功的解析一個源文件。這樣就使預(yù)解析 C++ 源碼變得不可能,并且使編寫代碼分析程序和語法制導(dǎo)的編輯器的過程十分難以正確實現(xiàn)。?
編譯器的復(fù)雜性。通過降低實現(xiàn)的復(fù)雜度,這就更有可能出現(xiàn)多個正確的實現(xiàn)。?
‘.’和‘->’之間的區(qū)別。這種區(qū)別其實很沒有必要。‘.’運算符完全可以起到‘->’所起的指針解引用的作用。
D 適合于?
經(jīng)常使用 lint 或者類似的代碼分析工具以期在編譯之前減少 bug 的程序員。?
將編譯器的警告級別調(diào)到最高的人和那些告訴編譯器把警告作為錯誤的人。?
不得不依靠編程風(fēng)格規(guī)范來避免常見的 C bug 的編程部門經(jīng)理們。?
認定 C++ 面向?qū)ο缶幊趟手Z的功能由于 C++ 太復(fù)雜而不能達到的人。?
沉溺于 C++ 強大的表達力但是被顯式內(nèi)存管理和查找指針 bug 折磨得精疲力盡的人。?
需要內(nèi)建的測試和驗證機制的項目。?
開發(fā)百萬行規(guī)模的程序的團隊。?
認為語言應(yīng)當(dāng)提供足夠的特征以避免顯式處理指針的程序員。?
編寫數(shù)值運算程序的程序員。D 擁有眾多直接支持?jǐn)?shù)值計算的特征,例如直接提供了復(fù)數(shù)類型和擁有確定行為的 NaN 和無窮大。(這些都被加進了最新的 C99 標(biāo)準(zhǔn),但是沒有加進 C++ 中。)?
D 的詞法分析程序和解析程序完全互相獨立,并且獨立于語義分析程序。這意味著易于編寫簡單的工具來很好地處理 D 源碼而不用編寫一個完整的編譯器。這還意味著源碼可以以記號的形式傳遞個某個需要它的程序。?
D 不適合于?
現(xiàn)實一點說,沒人會把上百萬行的 C 或 C++ 程序用 D 重新寫一遍,因為 D 不直接兼容 C/C++ 源代碼,D 并不適合于遺留程序。(但是,D 對遺留的 C API 提供了很好的支持。)?
非常小的程序——腳本或解釋性語言如 Python、DMDScript. 或者 Perl 更適合于這種情況。?
作為第一門程序設(shè)計語言—— Basic 或者 Java 更適合于初學(xué)者。對于中級到高級的程序員來說,D 是他們優(yōu)秀的第二門語言。?
語言純粹主義者。D 是一門實用的語言,它的每個特征都是為這個目的服務(wù)的,D并沒有想成為一門“完美”的語言。例如,D 擁有可以基本上避免在日常任務(wù)中使用指針的結(jié)構(gòu)和語義。但是 D仍然支持指針,因為有時我們需要打破這條規(guī)則。類似地,D 保留了類型轉(zhuǎn)換,因為有時我們需要重寫類型系統(tǒng)。編輯本段D 的主要特征 本節(jié)列出了一些更有趣的 D 的特征。?
面向?qū)ο缶幊?br /> 類
D 的面向?qū)ο筇煨詠碜杂陬悺2捎玫睦^承模型時單根繼承加接口。Object 類為與繼承體系的最頂端,所以所有的類都實現(xiàn)了一個通用的功能集合。類通過引用的方式實例化,所以不需要用于在異常后進行清理工作的復(fù)雜代碼。?
運算符重載
類可以通過重載現(xiàn)有的運算符擴展類型系統(tǒng)來支持新類型。例如創(chuàng)建一個 bignumber class ,然后重載 +、-、* 和 / 運算符,這樣大數(shù)類就可以使用普通的代數(shù)運算語法了。?
生產(chǎn)力
模塊
源文件同模塊是一一對應(yīng)的。D 不再“包含”帶有聲明的文件的文本,而是“導(dǎo)入”該模塊。不用擔(dān)心多次導(dǎo)入一個模塊,也不用再把頭文件用 #ifndef/#endif 或者 #pragma once 包起來了。?
聲明 vs 定義
C++ 的函數(shù)和類通常需要聲明兩次——聲明位于 .h 頭文件中,定義位于 .c 源文件中。這個過程易于出錯而且冗長繁瑣。顯然,應(yīng)該只需要程序員編寫一次,而由編譯器提取出聲明信息并將它導(dǎo)入到符號表中。這正是 D 所做的。?
示例:
class ABC { int func() { return 7; } static int z = 7; } int q;?
不再需要單獨定義成員函數(shù)、靜態(tài)成員、外部聲明之類的,也不需要像這樣煩人的語法:
int ABC::func() { return 7; } int ABC::z = 7; extern int q;?
注記:當(dāng)然,在 C++ 中,瑣碎的函數(shù)如 { return 7; }也可以直接寫在聲明處,但是復(fù)雜的函數(shù)就不行了(uframer:雖然從語法上說依然是可以的,但會違反 C++接口和實現(xiàn)分離的原則。)。另外,如果有前向引用的話,就必須保證已經(jīng)聲明了被引用的那個函數(shù)一個原型。下面的代碼在 C++ 中是不合法的:?
class Foo { int foo(Bar *c) { return c->bar; } }; class Bar { public: int bar() { return 3; } };?
但是等價的 D 代碼就可以正常工作:
class Foo { int foo(Bar c) { return c.bar; } } class Bar { int bar() { return 3; } }?
D 函數(shù)是否被在線化取決于優(yōu)化程序的設(shè)置。?
模板
D 模板提供了一種提供范型編程和偏特化能力的簡潔的方法。?
關(guān)聯(lián)數(shù)組
關(guān)聯(lián)數(shù)組是索引可以為任意類型的數(shù)組,不像普通數(shù)組那樣必須使用整數(shù)作為索引。本質(zhì)上,關(guān)聯(lián)數(shù)組就是散列表。關(guān)聯(lián)數(shù)組使構(gòu)建快速、高效、無錯的符號表變得容易了。?
真正的 typedef
C 和 C++ 的 typedef 實際上是類型 別名 ,因為它不會引入新的類型。D 實現(xiàn)了真正的 typedef :?
typedef int handle;?
實實在在地創(chuàng)造了一個新類型 handle 。D 同樣會對 typedef 引入的類型進行類型檢查,并且 typedef 也參與函數(shù)重載的決策。例如:
int foo(int i); int foo(handle h);?
Bit 類型
機器上最基本的數(shù)據(jù)類型是位,因此 D 直接支持 bit 數(shù)據(jù)類型。它在創(chuàng)建位數(shù)組時最有用:?
bit[] foo;?
函數(shù)
如你所愿,D 提供常規(guī)的對函數(shù)的支持,包括全局函數(shù)、重載函數(shù)、函數(shù)在線化、成員函數(shù)、虛函數(shù)、函數(shù)指針等等。另外,D 還支持:?
嵌套函數(shù)
函數(shù)可以嵌套在其他函數(shù)內(nèi)。這對于代碼分解、局部性以及函數(shù)閉包技術(shù)都具有很高的價值。?
函數(shù)文字量
匿名函數(shù)可以直接嵌入到表達式中。?
動態(tài)閉包
嵌套函數(shù)和類成員函數(shù)可以被稱為閉包(也被稱為委托),它們可使范型編程更為容易并保證類型安全。?
In, Out 和 Inout 參數(shù)
這幾個修飾符不只能使函數(shù)更為易于理解,還能避免使用指針而不會影響代碼的功能,另外這也會提高編譯器幫助程序員找到編碼問題的可能性。?
這些修飾符使 D 能夠直接同更多的外部 API 對接。也就無需使用“接口定義語言”(IDL)之類的東西了。?
數(shù)組
C 數(shù)組有幾個可以被糾正的缺點:?
數(shù)組本身并不帶有數(shù)組結(jié)構(gòu)的信息,它們必須另外存儲和傳遞。一個經(jīng)典的例子就是傳遞給main(int argc, char *argv[]) 函數(shù)的 argc 和 argv 參數(shù)。(在 D 中,main 被聲明為main(char[][] args) 。)?
數(shù)組不是一等公民。當(dāng)一個數(shù)組被傳遞給函數(shù)時,他被轉(zhuǎn)換為指針,盡管那個原型令人迷惑地聲稱它是一個數(shù)組。當(dāng)發(fā)生類型轉(zhuǎn)換時,所有的數(shù)組類型信息也就丟失了。?
C 數(shù)組的大小不可改變。這意味著即使最簡單的聚集如堆棧都必須用一個復(fù)雜的類構(gòu)造。?
C 數(shù)組沒有邊界檢查,因為它們根本不知道數(shù)組邊界是多少。?
數(shù)組聲明中的 [] 位于標(biāo)志符之后。這使得聲明如一個指向數(shù)組的指針這樣的東西都需要復(fù)雜難懂語法:?
int (*array)[3];?
在 D 中,數(shù)組的 [] 位于左側(cè):
int[3] *array; // 聲明了一個指向含有 3 個 int 的數(shù)組的指針 long[] func(int x); // 聲明了一個返回含有 long 數(shù)據(jù)的數(shù)組?
顯然這更易于理解。
D 數(shù)組有四種變體:指針、靜態(tài)數(shù)組、動態(tài)數(shù)組和關(guān)聯(lián)數(shù)組。?
字符串
在 C 和 C++ 中,對字符串的操作是如此的頻繁,而又如此的笨拙,以至于最好還是由語言本身來支持它比較好。現(xiàn)代語言都處理字符串連接、復(fù)制等等操作,D 語言也提供了這些支持。字符串是直接由經(jīng)過改進的數(shù)組來處理的。?
資源管理
垃圾收集
D 的內(nèi)存分配完全采用垃圾收集。經(jīng)驗告訴我們,C++ 中的很多復(fù)雜特征都是用于處理內(nèi)存釋放的。有了垃圾收集,語言就變得簡單多了。?
有一種看法認為垃圾收集是給那些懶惰、初級的程序員準(zhǔn)備的。我還記得那些對 C++ 的評論,畢竟,沒有什么 C++ 能做而 C 不能做的,或者這對匯編來說也一樣。?
采用垃圾收集可以避免 C 和 C++ 中必需的乏味的、易于出錯的內(nèi)存分配和追蹤代碼。這不只意味著更少的開發(fā)時間和更低的維護費用,還意味著程序運行得更快!?
當(dāng)然,可以在 C++ 中使用垃圾收集程序,我已經(jīng)在我自己的項目中使用它了。C++ 對垃圾收集程序并不友好,這也造成了 C++ 中垃圾收集的低效。很多運行時庫的代碼都不能同來垃圾收集程序一同工作。?
顯式內(nèi)存分配
盡管 D 是一種采用垃圾收集的語言,還是可以重寫某個類的 new 和 delete 操作以采用一個定制的分配器。?
RAII
RAII 是一種管理資源分配和釋放的現(xiàn)代軟件開發(fā)技術(shù)。D 以一種可控的、可預(yù)測的方式支持 RAII ,它是獨立于垃圾收集程序的回收周期的。?
性能
輕量級聚集
D 支持簡單的 C 風(fēng)格的結(jié)構(gòu),既保證了對 C 數(shù)據(jù)結(jié)構(gòu)的兼容性,也是因為有時采用類有殺雞用牛刀之嫌。?
內(nèi)聯(lián)匯編
設(shè)備驅(qū)動程序、高性能系統(tǒng)程序、嵌入式系統(tǒng)和某些特殊的代碼需要使用匯編語言完成任務(wù)。盡管 D 的實現(xiàn)不一定要實現(xiàn)內(nèi)聯(lián)匯編,它也仍被定義為語言的一部分。他可以滿足絕大多數(shù)使用匯編語言的需要,這樣就不需要單獨的匯編程序或者使用 DLL 了。?
許多的 D 實現(xiàn)同時也實現(xiàn)那些類似于 C 的支持 I/O 端口操作、直接訪問浮點硬件等內(nèi)部功能的內(nèi)函數(shù)。?
可靠性
現(xiàn)代的語言應(yīng)該竭盡所能地幫助程序員避免出錯。語言提供的幫助有多種形式:從易于使用更為健壯的技術(shù),到有編譯器指出明顯出錯的代碼,到運行時檢查。?
契約
契約式編程(由 B. Meyer 發(fā)明)是一種用于保證程序正確性的革命性的技術(shù)。D 版本的 DBC 包括函數(shù)先驗條件、函數(shù)后驗條件、雷不變量和斷言契約。?
單元測試
可以給一個類加入單元測試,這樣測試程序就能在程序啟動時自動運行。這樣就能夠在每次構(gòu)建時都驗證類是否實現(xiàn)了他所應(yīng)完成的功能。單元測試構(gòu)成了源代碼的一部分。創(chuàng)建單元測試成為了類開發(fā)過程中的自然的一部分,而不是將完成的代碼直接拋給測試小組。?
單元測試可以使用其它語言完成,但是其結(jié)果看起來有一種七拼八湊的感覺,而且你采用的那種語言很可能并不兼容這個概念。單元測試是 D 的一個主要特征。對于庫函數(shù)來說,單元測試已經(jīng)被證明是十分有效的。它既可以保證函數(shù)工作正常,也可以演示如何使用這些函數(shù)。?
考慮大量的可以從網(wǎng)上下載的 C++ 庫和應(yīng)用程序代碼。其中有“幾個”是帶有驗證測試的?更不要奢望單元測試了?少于 1% ?通常的做法是,如果它們能通過編譯,我們就假定它是正確的。而且我們不知道變異過程中給出的警告到底是真正的錯誤還是瞎嘮叨。?
契約式編程和單元測試使 D 為編寫可信賴、健壯的系統(tǒng)程序的最好的語言。單元測試還是我們能夠粗略但快速地估計你從未經(jīng)手的 D 代碼片斷的質(zhì)量——如果沒有單元測試和契約式編程,每人會干這種事。?
調(diào)試特征和語句
現(xiàn)在調(diào)試成為了語言語法的一部分了。可以在編譯時決定是否使用這些代碼,再也不用使用宏或者預(yù)處理命令了。調(diào)試語法提供了一種持續(xù)的、可移植的、易于理解的識別調(diào)試代碼的方法,使程序員既能夠生成帶有調(diào)試代碼的二進制版本,也能夠生成沒有調(diào)試代碼的二進制版本。?
異常處理
D 采用了更為高級的 try-catch-finally 模型而不是原來的 try-catch 模型。沒有必要只是為了利用析構(gòu)函數(shù)實現(xiàn) finally 語義而構(gòu)造一個傀儡對象。?
同步
因為多線程編程已經(jīng)越來越成為主流,所以 D 提供了構(gòu)建多線程程序的原語。同步既可以作用在方法上,也可以作用在對象上。
synchronized int func() { . }?
同步方法一次只允許一個線程執(zhí)行。?
同步語句將在語句塊周圍插入一個互斥體,控制對象或全局的訪問。?
對健壯性技術(shù)的支持
使用動態(tài)數(shù)組而不是指針?
使用對變量的引用而不是指針?
使用對對象的引用而不是指針?
使用垃圾收集而不是顯式內(nèi)存分配?
內(nèi)建線程同步原語?
不再有宏給你的代碼來那么一下子?
使用內(nèi)聯(lián)函數(shù)而不是宏?
在很大程度上減少了使用指針的需要?
整型的大小是明確的?
不用再擔(dān)心 char 類型是否有符號了?
不必再分別在源文件和頭文件中重復(fù)地寫聲明了?
為調(diào)試代碼提供了顯式的解析支持
編譯時檢查
更強的類型檢查?
需要進行顯式初始化?
不允許出現(xiàn)未使用的局部變量?
不允許出現(xiàn)空的(只由‘;’的)循環(huán)體?
賦值語句不會返回布爾類型的結(jié)果?
廢棄過時的 API?
運行時檢查
assert() 表達式?
數(shù)組邊界檢查?
switch 語句中的未定義 case 語句異常?
內(nèi)存耗盡異常?
in、out 和類不變量提供了對契約式編程的支持?
兼容性
運算符優(yōu)先級和求值規(guī)則
D 保留了 C 的運算符和它們的優(yōu)先級、求值的規(guī)則和類型提升規(guī)則。這就避免了由于同 C 的語義不同而造成的微妙的難以發(fā)現(xiàn)的 bug 的出現(xiàn)。?
直接訪問 C API
D 不支擁有同 C 類型對應(yīng)的類型,它還提供了直接訪問 C 函數(shù)的能力。完全沒有必要編寫封裝函數(shù)和參數(shù)變換器,也沒有必要逐一地復(fù)制聚集類型的成員。?
支持所有的 C 數(shù)據(jù)類型
使對 C API 或者現(xiàn)有的 C 庫代碼的接口成為可能。D 支持結(jié)構(gòu)、聯(lián)合、枚舉、指針和所有的 C99 類型。D 還擁有設(shè)置結(jié)構(gòu)成員對齊方式的能力,這樣就可以保證同外部導(dǎo)入的數(shù)據(jù)格式的兼容。?
操作系統(tǒng)異常處理
D 的異常處理機制將在應(yīng)用程序中利用底層操作系統(tǒng)提供的異常處理方式。?
使用現(xiàn)成的工具
D 生成標(biāo)準(zhǔn)的目標(biāo)文件格式,這樣就能夠使用標(biāo)準(zhǔn)的匯編程序、鏈接器、調(diào)試器、性能分析工具、可執(zhí)行程序壓縮程序和其他的分析程序,還能夠同其他語言編寫的代碼相鏈接。?
項目管理
版本控制
D 對從同一份源碼生成多個版本的程序提供了內(nèi)建的支持。它替代了 C 預(yù)處理程序的 #if/#endif 技術(shù)。?
廢棄
隨著代碼不停的演進,一些舊的庫代碼會被更新、更好的版本代替。同時舊的版本必須可用以支持舊的客戶代碼,舊的版本可以被標(biāo)記為 廢棄的。可以通過編譯器的一個選項來判斷使用廢棄版本代碼的版本是否是合法的,這樣一來負責(zé)維護的程序員就可以更為輕松的判斷哪里是依賴于已經(jīng)被廢棄的特征的。
沒有警告
D 編譯器不會為可疑的代碼生成警告。代碼要么可以被編譯器接受,要么不能被編譯器接受。這樣就不會引起有關(guān)哪些警告確實是錯誤而那些不是的爭論,也就沒有如何處理它們的爭論了。對編譯器警告的需求本身就是不好的語言設(shè)計的表現(xiàn)。
?
?
養(yǎng)成勵志的習(xí)慣,一生勵志???
22本經(jīng)典英語口語教程??
技術(shù)開發(fā)海量資料下載導(dǎo)航?
30本經(jīng)典Linux學(xué)習(xí)和開發(fā)教程和資料?
15本經(jīng)典C、C++、MFC、VC++教程
10本經(jīng)典Java教程
15本經(jīng)典Android教程和海量Android源碼
?
轉(zhuǎn)載于:https://www.cnblogs.com/javaTest/archive/2012/02/07/2589276.html
總結(jié)
以上是生活随笔為你收集整理的C++后继有人——D语言的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: html5 初试 indexedDB
- 下一篇: Node.Js 学习随笔2