楊 韜
(廣州致遠電子股份有限公司,廣東 廣州 510660)
?
用C語言實現類封裝的研究
楊 韜
(廣州致遠電子股份有限公司,廣東 廣州 510660)
多年以來,C語言在嵌入式軟件開發中被廣泛使用,但由于開發人員和應用場景等原因,面向對象、設計模式等優秀的軟件開發方法始終沒有很好地運用起來。時至今日,物聯網等應用的興起,給嵌入式軟件開發帶來新的挑戰,而傳統的面向過程開發已經難以支撐這些復雜的應用。因此,有必要在嵌入式軟件開發中引入面向對象、設計模式等優秀的軟件開發方法。面向對象是現代軟件方法的根基,面向對象體現在類上,而封裝為類的第一大特性。文章以類的封裝特性為切入點,結合C語言的特性,討論了C語言實現類封裝的方法,并給出了實例。
C語言;面向對象;類;封裝
物聯網等應用的興起,給嵌入式軟件開發帶來新的挑戰,而傳統的面向過程開發已經難以支撐這些復雜的應用。因此,有必要在嵌入式軟件開發中引入面向對象、設計模式等優秀的軟件開發方法。本文首先介紹了面向對象必要的基本概念,然后引入了UML類圖,通過使用C語言來實現一個Human類,討論了如何使用C語言來實現類的封裝特性,并給出了對應的分析。
1.1 對象[1]
對象是人們要進行研究的任何事物,從最簡單的整數到復雜的飛機等均可看作對象,它不僅能表示具體的事物,還能表示抽象的規則、計劃或事件。
對象具有狀態,一般用數據值來描述它的狀態。
對象還有操作,用于改變對象的狀態,對象及其操作就是對象的行為。
對象實現了數據和操作的結合,使數據和操作封裝于對象的統一體中。
1.2 面向對象
簡而言之,面向對象就是把客觀存在或主觀抽象的事物(即對象)抽象成類。
所謂抽象就是去異求同,從眾多的事物(即對象)中抽取出共同的、本質性的特征,舍棄其非本質的特征。比如香蕉、蘋果、哈密瓜等,它們共同的特性就是水果。得出水果概念的過程就是一個抽象的過程。在抽象時,同與不同,取決于從什么角度上來抽象。抽象的角度取決于分析問題的目的。
具有相同特性(數據元素)和行為(功能)的對象的抽象就是類。因此,對象的抽象是類,類的具體化就是對象,也可以說類的實例是對象。
1.3 類
面向對象有三大特性:封裝、繼承、多態,這些特性主要通過類來體現。類就是一個封裝了屬性以及相關操作的代碼的邏輯實體。
類具有屬性,它是對象的狀態的抽象,用數據結構來描述類的屬性。
類具有方法,它是對象的行為的抽象,用方法名和實現該操作的方法來描述。
除了封裝屬性和操作外,類還具有訪問控制的功能,比如,某些屬性和方法可以是私有的,不能被外界訪問,通過訪問控制,能夠對內部數據提供不同級別的保護,以防止外界意外地改變或使用了私有部分。不同的編程語言提供的訪問控制等級不盡相同,但都有公有、私有兩個等級。
類是抽象的數據類型,在內存中并不存在(Python等動態語言除外),只有類的實例存在于內存中。
在面向對象設計開發中,通常使用UML工具來進行分析設計。比如,可以使用UML類圖來描述類。
UML類圖很簡單,用一個矩形框代表一個類,矩形框內部被隔為三部分:上面部分為類的名字,中間部分為類的屬性,下面部分為類的方法。對于屬性和方法,還可以使用“+”、“-”修飾符來表示訪問權限,“+”為公有屬性、“-”為私有屬性。
如圖1所示,該類圖描述了一個名為“Human”的類。“Human”類抽象并封裝了“人”;屬性“name”是對人姓名的抽象,因為人的姓名是公開的,所以被設置為公有屬性;屬性“money”是對人所擁有的財富的抽象,因為每個人的財富都不是公開的,所以被設置為私有屬性;方法“buy”是對購物這一行為的抽象,方法“talk”是對講話這一行為的抽象,這兩個方法都是社會活動,所以被設置為公有屬性。

圖1 Human類圖
設計類的過程就是抽象的過程,抽象的結果取決于抽象時所站的角度,比如,如果是警察來抽象“Human”,他可能會添加一個“isBadGuy”屬性。
UML類圖主要用于輔助分析和設計階段,在設計類時應聚焦在與當前問題有關的重要屬性和行為,無關的屬性和方法統統去掉,確保UML類圖是簡潔有效的。除非私有屬性或方法會影響到問題的理解或者類的實現,否則UML類圖中不要出現私有屬性和方法,私有屬性通常在實現階段才會去考慮。
UML類圖以及其他UML元素都是輔助軟件開發的工具,使用UML進行設計時,只要相關人員能夠通過UML圖看懂你的設計、不妨礙溝通就可以了,即使用草稿紙來作圖也是可以的,所以,不用太過糾結那些細節,且一定要避免過度設計。
很多現代編程語言都有原生的面向對象支持,比如C++、JAVA、Python等,這些編程語言提供了class數據類型,在這些編程語言中類實際上就是一種數據類型,因此能夠更好地支持面向對象編程。
實際上,面向對象是與編程語言無關的,更像是一種思想,且不局限于軟件開發活動,任何需要分析解決問題的場合都可以使用面向對象。
C語言并沒有類的概念,但是可以從類的特性出發,利用C語言的某些特性來實現類的用法。關于類,首先要解決的就是封裝問題,類的封裝特性需要能夠封裝屬性和方法,還要有訪問控制。可以使用.h、.c文件和結構體來完成封裝。
下面以圖1中Human類的C語言實現為例來敘述C語言的類封裝問題,本文使用human.h、human.c、struct human三個元素來完成封裝,human.c為human.h中函數聲明的實現,本文不討論這些細節,所以只給出human.h的關鍵代碼片段,如下所示:
typedef struct human {
const char *name;
int _money;
} human_t;
human_t *human_init (human_t *p_this, const char *name, int money);
void human_talk (human_t *p_this, const char *p_words);
void human_buy (human_t *p_this, const char *p_something, unsigned price, unsigned count);
void human_deinit (human_t *p_this);
(1)類名
Human類的名稱體現在human.c、human.h以及human.h中所有全局符號的命名上,這些命名全部使用關鍵字human作為前綴。
(2)屬性
Human類的屬性體現在自定義類型human_t中,human_t實際上為結構體struct human,它有兩個成員:name和_money,分別對應類圖中的屬性+name和-money,特別留意_money成員前的“_”,這是為了警示類的使用者“此成員為私有屬性,不可使用”。
(3)方法
Human類的方法體現在human_talk()、human_buy()這兩個函數上,分別對應類圖中的方法+buy()和+talk()。此外,還可以注意到有human_init()、human_deinit()這兩個函數,分別為Human類的構造、析構方法。構造、析構方法分別用于類對象的初始化和解初始化。
構造函數human_init()需要用戶提供Human對象的內存,通過第一個參數p_this傳遞,對象的內存等價于一個human_t變量。
C語言中可以使用C文件中的static函數實現私有方法,假如Human類有私有方法money_pay(),則其C語言實現如下:
// human.c
static int __human_money_pay (human_t *p_this, unsigned cost)
{ … }
UML類圖中一般不會顯式地出現構造、析構和私有這三種方法,除非需要在類的構造、析構和實現上有特殊說明。
另外需要注意的是,這幾個方法函數的第一個參數都是human_t *類型,且名稱為p_this,這是C語言面向對象編程與面向過程的最大不同:p_this為指向類實例(即對象)的指針,所有的方法操作都需要“針對”一個對象,p_this指針由類的構造函數返回,比如,human_init()構造一個Human實例,然后返回指向此實例的p_this指針,然后就可以調用human_talk(p_this, …)等方法對實例進行操作。
(4)訪問控制
在Human類的C語言實現中,屬性被定義為human_t中的兩個成員,而 human_t被定義在用戶可見的human.h中,所以human_t是暴露給用戶的,因此,從語法上講,Human類的兩個屬性是暴露給用戶的,即都是公有屬性。雖然語法上不能支持私有,但可以在編程規范上設定“私有屬性以短下劃線“_”開頭”,比如“_money”,如此從某種意義上實現了屬性的訪問控制。
在Human類的C語言實現中,方法被定義為human.c中的函數。公共方法對應的函數都沒有“static”關鍵字,且在human.h中有對應的函數聲明。而私有方法對應的函數都有“static”關鍵字,這些私有方法只能在human.c文件內部調用,對用戶不可見。由此可知,C語言本身就能支持方法的訪問控制。
本文通過使用C語言實現一個Human類,討論了如何使用C語言來實現類的封裝特性。在C++等面向對象語言中,使用class對類做了原生的支持,使用起來非常簡單。盡管C語言并不是原生支持類,但通過語言、概念、規范上的處理,也能實現類的封裝特性。用C語言實現類的封裝相當于解決了C面向對象的關鍵第一步,在其基礎之上可以引入更多現代軟件方法。
[1] 百度. 百度百科/面向對象[EB/OL].[2016-08-08].http://baike.baidu.com/link?url=6XlXEOSlrKn87S7SJv4UW SX7EjstoDVm-wJ13OAod-XUrUrnZkVg3ntPFir-Ey5c6mqObZZ OevQI6K3Ungq1Mq.
Research on the implementation of class encapsulation with C-language
Yang Tao
(Guangzhou Zhiyuan Electric Co. Ltd. , Guangzhou 510660, China)
For many years, C-language is widely used in embedded software development, but because of the developers and application scenarios and other reasons, object-oriented, design patterns and other outstanding software development methods have not been well used. Today, the development of Internet of Things and other applications, has brought new challenges to the development of embedded software, and the traditional process-oriented development has been difficult to support these complex applications. Therefore, it is necessary to introduce object-oriented, design patterns and other excellent software development methods in embedded software development. Object oriented method is the foundation of modern software, object-oriented is embodied in the class, encapsulation is the first major characteristic. In this paper, the characteristics of encapsulation as the starting point, combined with the characteristics of C-language, the method of C-language encapsulation is discussed, and an example is given.
C-language; object-oriented; class; encapsulation
TP312
A
10.19358/j.issn.1674- 7720.2016.21.007
楊韜. 用C語言實現類封裝的研究[J].微型機與應用,2016,35(21):24-25,29.
2016-09-01)
楊韜(1986-),男,學士,工程師,主要研究方向:嵌入式系統、軟件工程、軟件方法。