趙 輝,屈 雷
(西安工程大學 電子信息學院,陜西 西安 710048)
C語言是在國內外廣泛使用的一種高級編程語言[1]。其功能豐富、使用靈活方便、目標程序效率高、可移植性好,既具有高級語言的優(yōu)點,又具有低級語言的諸多特性。因此,C語言特別適合用于編寫系統(tǒng)軟件[2],其中著名的Linux/Unix操作系統(tǒng)就是用C語言編寫而成的[3]。
一般來說,C語言是以面向過程的方式進行編程的,用來編寫功能復雜的軟件是比較困難的[4]。而Linux/Unix操作系統(tǒng)卻是使用C語言編寫,并與面向對象程序設計的思想相結合[5],提升了C語言的簡潔性、易讀性和重復使用性,進而提高了系統(tǒng)分析及結構設計的能力[6]。這一例子說明,C語言其實也可以像C++一樣以面向對象的方式進行編程。
本文將通過電子書軟件來具體分析,如何使用面向對象編程中的一些機制來實現(xiàn)C語言的面向對象設計。
當人們提到面向對象的編程語言,首先想到的會是C++。在1985年以前,C++的名字是“C with Class”,從名字上可以看出C++最突出的特征就是類(Class);從另一種角度可以看出C++是C語言的有效擴充[7]。所以使用ANSI-C進行面向對象的編程,最基礎的是類機制,而且還需要其他機制的支持。
“Class”是很多面向對象編程語言里定義類的關鍵字,它來源于最早的編程語言——smalltalk。類是一群具有共同屬性的對象,說明了這群對象所具有的特征和行為。在程序中,數(shù)據表示對象的特征,函數(shù)表示對象的行為[4]。
類可以理解為用戶定義的一種新的數(shù)據類型,就像是“short”這樣的內置類型一樣。內置類型已經有了一套完善的操作(如算數(shù)運算等),類機制也必須規(guī)定他所定義的類也能夠進行操作,即對象的行為。在ANSI-C中并沒有關鍵字“class”,但是可以使用結構體(struct)來定義一種新的數(shù)據類型,從而實現(xiàn)類。在結構體定義里,使用變量來描述對象的特征,并使用函數(shù)指針來描述對象的行為。
面向對象程序設計的主要優(yōu)點之一就是提供軟件元素的重用。它提供了幾種機制支持利用已有類來定義新類,新類可以獲得已有類的特征和行為,進而實現(xiàn)類的重用。本文實現(xiàn)了一種比較簡單的重用機制即組合。
組合(composition)表示的是兩個對象之間獲得一種包含關系,即一個對象包含或擁有另一個對象[8]。擁有其他對象的對象被稱為組合體,它所擁有的對象被稱為組件。這種關系在現(xiàn)實生活中是很普遍的:計算機包含處理器,書本包含文字等。組合使用ANSI-C實現(xiàn)是很簡單的。
封裝(encapsulation)是面向對象的另一個重要概念。就是把特征和行為包圍起來,對數(shù)據的訪問只能通過特定的接口。事實上,封裝就是用戶對信息的隱藏,保證了模塊具有較好的獨立性,使得程序維護修改較為容易。對應用程序的修改僅限于類的內部,因而可以將應用程序修改帶來的影響減少到最低限度[9]。
非 OOP(Object Oriented Programming)語言沒有完備的機制來實現(xiàn)封裝[6]。使用ANSI-C來實現(xiàn)封裝稍微有些復雜。本文使用單向鏈表實現(xiàn)了對類中所有實例化的對象進行封裝。
多態(tài)(polymorphism)源于希臘語,意思的“多種形狀”。在OOP語言中多態(tài)是指相關對象具有不同的成員函數(shù)(函數(shù)原型相同),并且允許對象與適當?shù)某蓡T函數(shù)運行時進行動態(tài)綁定[6]。多態(tài)保證了軟件設計的重復使用。一般通過虛方法實現(xiàn)多態(tài)[10]。
一般情況下,我們使用ANSI-C編程,函數(shù)的原型是對應唯一的函數(shù)實現(xiàn)。而多態(tài)要求一個函數(shù)原型可以對應多個函數(shù)實現(xiàn),這樣可以便于管理功能相似的模塊。如果前面提到的類機制、重用機制和封裝機制都已經使用ANSI-C實現(xiàn),再要實現(xiàn)多態(tài)機制就是非常簡單的事情,使用函數(shù)指針抽象出統(tǒng)一的函數(shù)接口。
整個軟件使用了ANSI-C編寫,采用上文所提到的面向對象的實現(xiàn)方法,并進行模塊化分層設計。
(1)支持多種字體編碼方式。文本文件一般有四種編碼方式:ANSI、Unicode、Unicode big endian、UTF-8。程序需要根據文本文件的編碼方式,自動選擇解碼函數(shù)。
(2)支持多種字體顯示方式。常用的字體顯示方式有GBK點陣和freetype矢量字體。程序需要根據字體設置,判斷使用哪種方式顯示文字。
(3)支持多種輸入方式。常見的輸入方式有鍵盤和觸摸屏。程序要根據鍵盤的輸入和觸摸屏的滑動,實現(xiàn)翻頁。
(4)支持多種設備顯示。程序在PC機上運行是,使用PC機的顯示器(CRT)。程序在ARM上運行時,使用ARM上的LCD顯示器。
根據電子書軟件需求,將整個軟件分3層。軟件的層次關系及各功能模塊構成如圖1所示。面向對象的實現(xiàn)方法主要體現(xiàn)為4個基本的底層功能模塊,每個模塊分別有幾種不同的實現(xiàn)方式。并由一個管理文件提供接口函數(shù)對不同的實現(xiàn)方式進行統(tǒng)一的操作。中間層為電子書頁面管理模塊,負責調用底層實現(xiàn)的接口函數(shù)實現(xiàn)了字體顯示和頁面操作以及相關的初始化。頂層為電子書管理模塊,負責調用中間層實現(xiàn)的相關數(shù)據管理成個程序。
(1)使用arm-linux-gcc工具鏈在Ubunut上編譯,在飛凌的ok6410開發(fā)板上運行,結果如圖2所示。
(2)首先在Ubunut上移植svgalib庫,其次使用gcc在Ubunut上編譯,最后在Ubunut上的tty控制臺運行程序。結果如圖3所示。
電子書程序的代碼量比較大,無法全部分析。本文將針對設備顯示模塊進行詳細分析,具體如下。
圖1 在ARM的LCD上顯示的結果
圖2 在ARM的LCD上顯示的結果
圖3 在PC機的CRT上顯示的結果
根據實驗需求,本程序可以在PC機的CRT上顯示,也可以在ARM的LCD上顯示。所以我們需要操作的對象就是CRT和LCD。我們能夠抽象出他們的共同特征和行為,得到一個具體類,使用結構體實現(xiàn)。具體代碼如下,這部分定義在disp_manager.h頭文件中:
其中T_Disp結構體是顯示器固有屬性的抽象,也是T_DispOpr類的一部分,這樣就可以簡單的實現(xiàn)ANSI-C中的類和組合機制。
根據上文產生的具體類,實例化為CRT和LCD對象,分別實現(xiàn)在crt.c和lcd.c文件中。一個C文件實現(xiàn)具體類的一個實例化,這樣的模塊化設計,使得程序進行添加和刪除模塊簡單方便,更容易維護。由于對具體類的實例化是非常相似的,本文只對LCD對象的實例化進行具體分析,代碼如下:
上面的代碼給出了3個函數(shù)聲明,具體的實現(xiàn)過程略。代碼中使用了“static”關鍵字,說明定義的是靜態(tài)函數(shù)和靜態(tài)變量。這些函數(shù)和變量只能在本文件中被調用,這也是實現(xiàn)封裝的基礎。那么上層的函數(shù)怎么調用這些靜態(tài)函數(shù)和靜態(tài)變量?
在lcd.c文件中需要有一個入口函數(shù),以便實現(xiàn)其他文件對本文件中靜態(tài)函數(shù)和靜態(tài)變量的調用。代碼如下:
其中RegisterDispOpr()函數(shù)將g_tLCDOpr結構體的地址注冊到單向鏈表中。上層函數(shù)就是通過鏈表找到g_tLCDOpr結構體的入口地址,調用相關的函數(shù)及變量。實現(xiàn)了將具體類例化的對象封裝到鏈表中。這個函數(shù)是在disp_manager.c文件中實現(xiàn),而在這個文件中還需要實現(xiàn)一些操作鏈表的通用函數(shù),方便上層函數(shù)調用。
在lcd.c文件中
/*LCD設備初始化函數(shù)*/
.DeviceInit =LCDDeviceInit,
在crt.c文件中
/*CRT設備初始化函數(shù)*/
.DeviceInit =CRTDeviceInit,
程序在調用這個兩個函數(shù)時,使用的是同一個接口 g_ptDispOpr->DeviceInit(),這就是多態(tài)的實現(xiàn)。程序先在鏈表中根據g_ptDispOpr->name查找,返回相應name的結構體的入口地址,進而就確定了g_ptDispOpr->DeviceInit()接口對應的是哪個具體的實現(xiàn)過程。
如今嵌入式軟件應用愈來愈廣,軟件的質量決定了數(shù)碼產品的穩(wěn)定性和可靠性。本文的實現(xiàn)的這些機制對于嵌入式軟件編程是大有裨益。但是,對于大型的軟件系統(tǒng)來說,本文實現(xiàn)的這些機制是遠遠不夠的。可能還需要超類、繼承、內存泄漏檢測等機制的支持。
[1]黃俊爽,郭凌云,李燕杰,等.淺析C語言中常見錯誤[J].電腦知識與技術,2010(12):60.
[2]譚浩強.C語言程序設計[M].3版.北京:清華大學出版社,2005.
[3]丁慧.用C語言實現(xiàn)面向對象研究[J].淮海工學院學報:社會科學版,2010,8(12):61-63.
[4]曹燁.淺談C語言與匯編語言混合編程的實現(xiàn)[J].科技信息:科學教研,2008(17):1001-9960.
[5]高煥堂.UML+OOPC嵌入式C語言開發(fā)精講[M].北京:電子工業(yè)出版社,2008.
[6]陳飛,陳啟安.面向對象的嵌入式系統(tǒng)開發(fā)技術[J].單片機與嵌入式系統(tǒng)應用,2005,5(9):15-18.
[7]LINDEN P V D,徐波.C專家編程[M].北京:人民郵電出版社,2002.
[8]LASZLO M J,楊秀梅,何玉潔,等.面向對象程序設計——圖形應用實例[M].北京:機械工業(yè)出版社,2002.
[9]鄧正宏,薛靜,鄭玉山.面向對象技術[M].北京:國防工業(yè)出版社,2004.
[10]丁智,王睿,高艷萍,等.標準C實現(xiàn)面向對象編程[J].江西科學,2009,27(5):733-736.