維護頭文件通常是一個冗長乏味并且容易出錯的過程,感謝.NET assembly類庫抹去了對這些文件的倚賴。
微軟.NET的可管理的C++最終簡化了我們創建類庫的方法,或更準確些,.NET assembly類庫,這種簡化得以實現主要是由于assembly類庫是可以自我描述的。這對一個Managed C++程序員意味著什么呢?基本上講,一旦 assembly編譯成功,你在編譯傳統C++類庫的時謹慎創建的所有頭文件除了維護的需要外,都不再是必需的。
就個人而言,我感覺維護頭文件是一種痛苦,所以我很高興看到這種對頭文件的倚賴正在消失。我經常會忘記需要在庫中引用的一個或多個頭文件的名稱,為了找到缺失的數據類型定義,我不得不對所有含有頭文件的內容進行搜索,更糟糕的是,將源代碼拆分為兩半增加了我犯錯誤的機會。我經常犯的錯誤包括忘記將所有的包含頭文件打包、使.h文件和.cpp脫離同步。
既然對頭文件的程序集不再是必需的,你可以使用一種改進了的新方法來創建源文件。但在考察這種方法之前,先讓我們先來回顧一下創建程序集的傳統方法
傳統方法
在C++中,傳統的庫文件創建方法是建立一系列頭文件用以描述類庫中所有的功能;接下來,你要在一個單獨的源文件中實現這些頭文件所定義了的所有功能。然后,在編譯器中運行每一個源代碼文件連同其相關的頭文件,以生成目標文件;再將所有的目標文件相互鏈接來創建庫文件
圖A描述了這種傳統方法。
圖A
創建庫的傳統方法
使用頭文件的原因在于,今后引用這個類的時候,所有的類、結構體、變量等等都可以很方便的定義。
程序集可以使用同樣的方法生成,這一過程的唯一區別在于Managed C++的標志是事先確定的。
在下面的例子中,列表A、B、C和D演示了如何用傳統C++的方法創建一個 assembly。
列表A給出了頭文件Cards.h的定義,這個文件定義了一個包含撲克牌和Card類的枚舉(enmu),注意,使用ManagedC++時,關鍵字public要放在enum和class之前的,因為這兩者都需要在全局范圍內可以被訪問。
列表B展示了類的構造器和成員方法的實現,列表C定義了第二個類Deck,注意,雖然從來沒有在頭文件中定義,但Card類是在Deck類之內使用的,使用這一技巧需要謹記:在編譯過程中,頭文件基本上是大批量地粘貼到源文件中的。既然是這樣的情況,我們只需簡單地在Deck.cpp源文件的包含文件列表中將Card.h放在Deck.h的前面,如此操作之后,Card類將首先被粘貼,繼而被定義為Deck類所必需的類。
列表D顯示了在這個迷你庫中的源文件,注意,正如我們剛剛所提到的,Card.h包含在Deck.h之前。
在命令行中執行建立 assembly庫的命令并不像火箭科學一樣艱難,其語法(沒有這些省略號)非常簡單:
cl source1.cpp source2.cpp ... sourceN.cpp /CLR /LD /o OutputName.dll
C++編譯器取走這一系列源文件的名稱,然后是/CLR參數,它告訴編譯器我們正在使用managed的擴展,繼而/LD參數告訴連接器去創建一個.dll文件,最后/o參數將說明這個.dll文件的名稱。
為了編譯以上的例子,你可能會用到這行命令:
clcard.cppdeck.cpp /CLR /LD /o cards.dll
新的 assembly方法
不再受困于分離頭文件和源文件的工作,就為新的庫文件編碼方式提供了可能性。在兜了一個圈子之后,我將開始介紹我的簡便方法,首先,將所有的類以類文件(.h)形式進行編碼,其中包括所有的定義和實現;然后使用一個單獨的連接器文件(.cpp)來包含所有的類文件;這種方法唯一有些棘手的部分在于,你要確定所有的類文件是按照正確的順序排列的,以保證一切需要調用的數據類型在使用之前都已經定義好了,即使使用傳統方法,這一問題同樣需要處理。圖B展示了這種新的 assembly方法。
圖B
新的 assembly方法
采用這種方法,你只需維護半數文件,既然定義和源碼是一同定義的,就不會造成不同步的。這樣一來,維護庫的工作就簡單了很多,另外,開發文檔只需保存在一個地方,也就更容易閱讀,所有這些都說說明了這是一種更好的方法。
列表E、F和G展示了使用新方法生成的同樣的庫。
正如你看到的那樣,列表E是傳統方法中Card.h和Card.cpp這兩個文件相結合而形成的,我基本上只是把實現部分直接放在類的定義中,而不是在一個單獨的文件中進行定義。
同樣的,列表F是傳統方法中Deck.h和Deck.cpp這兩個文件相結合形成的,如果使用傳統方法,你可以在這個類中訪問其他的類而不必在文件中定義他們,連接器文件需要確保所有類的定義是按照正確的順序排列的,以保證這些類在使用之前都已經定義好了。
在列表G中顯示的連接器文件是唯一一個與眾不同的文件,它除了包含語句之外沒有任何其他的東西,ManagedC++編譯器只編譯.cpp文件,為了讓編譯器完成所有的工作,你必須有這個文件。這種便利所帶來的副作用是從庫中添加或刪除類變得容易了,而你已經將組成庫的類名稱記錄在了一個單一的地方。在開發過程中,連接器文件還是一個放置測試代碼的理想場所。
以這種方法建立一個assembly類庫的額外的優點是,在命令行條件下使用時,其命令很簡單:
clcards.cpp /CLR /LD
結論
具有自我描述功能的 assembly器簡化了我們編碼的方法,這主要是因為源代碼模塊不再需要被分離為頭文件和源碼文件,正因為得益于此,我們展示了一種構造 assembly庫的新方法。
責任編輯:李寧
|