摘要:C++和Java是目前使用相當(dāng)廣泛的兩種面向?qū)ο蟪绦蛟O(shè)計(jì)語(yǔ)言,該文對(duì)二者的OOP實(shí)現(xiàn)機(jī)制之差異性進(jìn)行分析,從封裝性、繼承性和多態(tài)性三個(gè)方面進(jìn)行探討,為熟練使用C++和Java進(jìn)行OOP編程提供幫助。
關(guān)鍵詞:封裝性;繼承性;多態(tài)性;差異性
中圖分類號(hào):TP311文獻(xiàn)標(biāo)識(shí)碼:A文章編號(hào):1009-3044(2012)03-0599-02
C++和Java是目前主流的兩種面向?qū)ο蟮某绦蛟O(shè)計(jì)語(yǔ)言。C++是編譯型,而Java是解釋型。C++執(zhí)行速度快,而Java可移植性好,C++適合底層編程,而Java擅長(zhǎng)于WEB系統(tǒng)和嵌入式消費(fèi)電子設(shè)備編程。C++和Java都于基于OOP理論設(shè)計(jì)出來的,所以它們?cè)诨菊Z(yǔ)法和核心概念上有許多相似之處,然而它們之間在OOP的實(shí)現(xiàn)機(jī)制上存在不容忽視的差異。本文分析C++和Java在OOP實(shí)現(xiàn)機(jī)制上的差異。
1 OOP基本概念分析
OOP(Object-Oriented Programming)面向?qū)ο缶幊淌悄壳白钪髁鞯某绦蛟O(shè)計(jì)思想,其核心內(nèi)容由三部分組成:封裝性、繼承性和多態(tài)性。
1.1封裝性
封裝就是把數(shù)據(jù)和操作數(shù)據(jù)的方法結(jié)合在一起,形成一個(gè)類,外面的類不能隨意訪問這些數(shù)據(jù),通常提供公用方法來訪問數(shù)據(jù)。類和方法是封裝性的核心概念。類是一類事物的抽象,包含這類事物的描述和可進(jìn)行的動(dòng)作。按照類的模板建立的實(shí)例,叫做對(duì)象。例如“教師”就可以抽象為一個(gè)類,其數(shù)據(jù)包括教師編號(hào)、姓名、性別等,其方法包括備課、講課、輔導(dǎo)等,具體到某一個(gè)教師如“李華老師”,他就是一個(gè)對(duì)象。
1.2繼承性
繼承性所表達(dá)的是類之間的相互關(guān)系,為程序代碼的復(fù)用提供了良好的支持。繼承機(jī)制的核心概念是父類和子類,也叫基類和派生類。派生類繼承基類的數(shù)據(jù)和操作,也就是說允許派生類使用基類的數(shù)據(jù)和操作。同時(shí)派生類也可以增加新的數(shù)據(jù)和操作。例如汽車可以抽象為一個(gè)基類,警車類可以作為派生類,它繼承了汽車類的有四個(gè)車輪及可以移動(dòng)的特性,還可以增加新的特性,如有警燈、警笛和優(yōu)先通行等特性。
1.3多態(tài)性
多態(tài)性指不同的對(duì)象收到相同的消息時(shí)產(chǎn)生多種不同的行為方式。例如一個(gè)司機(jī)的車停在了別人的車位上,司機(jī)可能會(huì)收到別人給他的消息—“請(qǐng)把您的車挪開”,在圖書館里司機(jī)的凳子擋住了別人的去路,司機(jī)可能會(huì)收到別人給他的消息—“請(qǐng)把您的凳子挪開”。在這兩種情況下司機(jī)收到的都是“挪開”一樣?xùn)|西的消息,但是在聽到“挪開”請(qǐng)求以后的行為是截然不同的。這就是多態(tài)性,多態(tài)性的核心概念是重載和覆蓋。
2封裝性之差異性分析
C++擁有OOP的特性,同時(shí)也繼承了C的許多面向過程的特性,如全局變量、結(jié)構(gòu)體和枚舉等,所以C++包含了面象過程編程和面向?qū)ο缶幊痰碾p重概念。然而Java卻是一種完全面向?qū)ο蟮木幊陶Z(yǔ)言,它所有的程序都是由類或者說類的定義組成的。
2.1類的定義之差異
類的組成通常是數(shù)據(jù)和操作,它們?cè)贑++中通常稱為成員數(shù)據(jù)和成員函數(shù),在Java中通常稱為屬性和方法。在C++中函數(shù)可以定義在類中,作為成員函數(shù),也可以不定義在類中,作為獨(dú)立的函數(shù);數(shù)據(jù)可以定義在類中,作為成員數(shù)據(jù),也可以定義在類外,作為全局變量。在Java所有的方法和屬性必須定義在某個(gè)類中,禁止在類外對(duì)方法和屬性進(jìn)行定義,更符合其完全面向?qū)ο蟮奶攸c(diǎn)。
在C++中不可以在一個(gè)類的內(nèi)部定義另一個(gè)類,也就是說不支持類的嵌套定義,而Java支持類的嵌套定義,稱之為內(nèi)部類。
2.2對(duì)象的建立與銷毀之差異
C++和Java對(duì)象建立過程中分配空間的時(shí)機(jī)不同。假若有一個(gè)類Point,語(yǔ)句Point p在C++中的含義是定義一個(gè)對(duì)象p,同時(shí)為對(duì)象p分配存儲(chǔ)空間;語(yǔ)句Point p在Java中含義卻只是定義一個(gè)實(shí)例變量p,并沒有分配存儲(chǔ)空間,只有執(zhí)行了p=new Point()后才完成了存儲(chǔ)空間的分配,生成了對(duì)象。
C++中對(duì)象的生成和銷毀都是通過編程人員編寫程序代碼來完成的,對(duì)象的生成需要編寫構(gòu)造函數(shù),對(duì)象的銷毀需要編寫析構(gòu)函數(shù),在需要生成對(duì)象時(shí)自動(dòng)調(diào)用構(gòu)造函數(shù),在對(duì)象銷毀時(shí)自動(dòng)調(diào)用析構(gòu)函數(shù),內(nèi)存空間是由編程人員負(fù)責(zé)管理的。
Java中對(duì)象的生成需要調(diào)用構(gòu)造方法,這和C++中一樣。但在Java中為簡(jiǎn)化編程,對(duì)象銷毀時(shí)的空間回收是由系統(tǒng)的垃圾回收機(jī)制自動(dòng)完成的,Java不支持析構(gòu)方法,在必要的時(shí)候也可以創(chuàng)建一個(gè)方法來完成存儲(chǔ)空間的回收。
當(dāng)由已經(jīng)存在的對(duì)象建立一個(gè)新對(duì)象時(shí),C++使用拷貝構(gòu)造函數(shù),將參數(shù)代表的對(duì)象逐域拷貝到新創(chuàng)建的對(duì)象中。在Java中沒有拷貝構(gòu)造函數(shù),因?yàn)閷?shí)例變量是按引用傳遞的。
3.1多重繼承與接口
多重繼承是指一個(gè)子類可以有一個(gè)以上的直接父類。C++支持多重繼承,而Java不支持多重繼承,而是使用接口來實(shí)現(xiàn)多重繼承的功能。接口就是方法定義和常量值的集合,一個(gè)接口可以繼承多個(gè)父接口,子接口繼承父接口中所有的常量和方法。在Java中一個(gè)類只能有一個(gè)父類,卻可以實(shí)現(xiàn)多個(gè)接口,達(dá)到了比多重繼承更強(qiáng)的功能。
3.2繼承方式
C++中的繼承方式有公有繼承、保護(hù)繼承和私有繼承,在Java中只有一種繼承,那就是公有繼承,所以在Java中繼承不會(huì)改變父類成員的保護(hù)級(jí)別。
4多態(tài)性之差異性分析
多態(tài)性是指用一個(gè)名字定義不同的函數(shù),即函數(shù)名相同而函數(shù)體不同,也就是用同樣的接口訪問功能不同的函數(shù),實(shí)現(xiàn)了“一個(gè)接口,多種方法”。多態(tài)性分為靜態(tài)多態(tài)性和動(dòng)態(tài)多態(tài)性。在程序運(yùn)行之前就可以確定要調(diào)用哪個(gè)函數(shù),稱為靜態(tài)多態(tài)性也叫靜態(tài)綁定;一直要到程序運(yùn)行時(shí)才能確定調(diào)用哪個(gè)函數(shù),稱為動(dòng)態(tài)多態(tài)性也叫動(dòng)態(tài)綁定。
4.1靜態(tài)多態(tài)性差異性分析
靜態(tài)多態(tài)性在C++中是通過函數(shù)重載和運(yùn)算符重載來實(shí)現(xiàn)的,Java只支持方法重載不支持運(yùn)算符重載。函數(shù)重載如果發(fā)生在一個(gè)類中,那么函數(shù)的形式參數(shù)的類型或者個(gè)數(shù)必須要有所不同,如果函數(shù)重載時(shí)函數(shù)的參數(shù)類型和參數(shù)個(gè)數(shù)完全相同,這時(shí)通常是發(fā)生在有繼承關(guān)系的不同類中。后者常稱為覆蓋。
4.2動(dòng)態(tài)多態(tài)性差異性分析
在C++中是通過基類指針變量和虛函數(shù)來實(shí)現(xiàn)的,在Java中是通過基類對(duì)象的引用來實(shí)現(xiàn)的。下面比較兩者實(shí)現(xiàn)的差異。
在C++中基類指針變量可以指向基類對(duì)象或者其派生類對(duì)象。例如有基類Shape和基類指針變量Shape *p,基類Shape中一個(gè)成員函數(shù)area()在其派生類Rectangle和Circle中被覆蓋,這時(shí)無(wú)論基類指針變量p指向基類對(duì)象或者派生類Rectangle及Circle對(duì)象,通過基類指針變量來訪問成員函數(shù)area(),即p-> area(),所執(zhí)行的函數(shù)均為基類Shape中的area()函數(shù),而不會(huì)根據(jù)基類指針變量p指向不同的派生類對(duì)象而執(zhí)行相應(yīng)的派生類中的函數(shù),并沒有實(shí)現(xiàn)動(dòng)態(tài)多態(tài)性。
要想實(shí)現(xiàn)多態(tài)性需要把基類Shape中的成員函數(shù)area()定義為虛函數(shù),即在函數(shù)頭前面加上關(guān)鍵字Virtual,這時(shí)通過基類指針變量p來訪問成員函數(shù)area(),即p-> area(),就會(huì)根據(jù)p所指向的對(duì)象的不同,而調(diào)用相應(yīng)對(duì)象的area()函數(shù),實(shí)現(xiàn)了動(dòng)態(tài)多態(tài)性。
在Java中基類變量可以引用基類對(duì)象或者其派生類對(duì)象,與上例類似假如有基類Shape和基類變量Shape p,基類Shape中一個(gè)成員函數(shù)area()在其派生類Rectangle和Circle中被覆蓋,這時(shí)通過基類變量p來訪問成員函數(shù)area(),即p.area(),就會(huì)根據(jù)p所引用的對(duì)象的不同,而調(diào)用相應(yīng)對(duì)象的area()函數(shù),實(shí)現(xiàn)動(dòng)態(tài)多態(tài)性,Java沒有虛函數(shù)的概念。
純虛函數(shù)和抽象方法。在上例中基類Shape體現(xiàn)了一個(gè)抽象的概念,在其中定義函數(shù)area()顯然是無(wú)意義的,此時(shí)可以只定義其函數(shù)頭,不定義其函數(shù)體,基類Shape的各派生類可根據(jù)需要實(shí)現(xiàn)屬于自己的函數(shù)area()。在這種情況下,在C++中,基類Shape中的函數(shù)area()稱為純虛函數(shù),定義格式為virtual void area()=0;在Java中基類Shape中的函數(shù)area()稱為抽象方法,定義格式為abstract void area()。在C++中含有一個(gè)或多個(gè)純虛函數(shù)的類及在Java中含有一個(gè)或多個(gè)抽象方法的類,稱之為抽象類。抽象類不能實(shí)例化,即不能生成對(duì)象。
5結(jié)束語(yǔ)
以上對(duì)C++和Java在面向?qū)ο缶幊谭矫娴幕靖拍钸M(jìn)行了差異分析,當(dāng)然它們的差異還有很多,本文只是對(duì)較為常用的方面進(jìn)行了簡(jiǎn)單的比較與分析。這種分析不在于分出兩種語(yǔ)言的高下,而在于更好地運(yùn)用OOP思想并靈活運(yùn)用高級(jí)語(yǔ)言去設(shè)計(jì)程序,解決問題。
參考文獻(xiàn):
[1]戴特爾.C++大學(xué)教程[M]