說起面向?qū)ο?,大家可能?huì)想到其他的,但是此對(duì)象非彼對(duì)象哈哈,不必驚慌,也特別好搞定。
在聽到面向?qū)ο笾按蠹乙惨欢〞?huì)接觸學(xué)習(xí)到面向過程相關(guān)的,那么它們兩個(gè)之間到底是有什么關(guān)系呢,我先給咱嘮嘮。
面向過程與面向?qū)ο蟮膮^(qū)別
面向過程—步驟化
當(dāng)軟件規(guī)模超過一定的尺度后,采用結(jié)構(gòu)化程序設(shè)計(jì),其開發(fā)和維護(hù)就越來(lái)越難控制。其根本原因就在于面向過程的結(jié)構(gòu)化程序設(shè)計(jì)的方法與現(xiàn)實(shí)世界往往都不一致,結(jié)構(gòu)化程序設(shè)計(jì)的思想往往很難貫徹到底。
在結(jié)構(gòu)化程序設(shè)計(jì)中,采用的是“ 自頂向下,逐步細(xì)化 ”的思想。具體操作方法是模塊化,是按功能來(lái)分的,所以也稱功能塊。在C++中稱為一個(gè)函數(shù),一個(gè)函數(shù)解決一個(gè)問題,即實(shí)現(xiàn)一個(gè)功能或一個(gè)操作。
在模塊化的思想中已經(jīng)出現(xiàn)了封裝的概念,這個(gè)封裝是把數(shù)據(jù)封裝到模塊中,即局部變量。但這是很不徹底的,因?yàn)槟K是功能的抽象,而數(shù)據(jù)則是具有其個(gè)性的,一旦發(fā)生哪怕是一點(diǎn)變化,抽象的功能模塊就不再適用了??删S護(hù)性差成了制約機(jī)構(gòu)化程序設(shè)計(jì)應(yīng)用的瓶頸。
總的來(lái)說,面向過程就是分析出實(shí)現(xiàn)需求所需要的步驟,通過函數(shù)一步一步實(shí)現(xiàn)這些步驟,接著依次調(diào)用即可。
面向?qū)ο蟆袨榛?/p>
面向?qū)ο笫前颜麄€(gè)需求按照特點(diǎn)、功能劃分,將這些存在共性的部分封裝成類(類實(shí)例化后才是對(duì)象),創(chuàng)建了對(duì)象不是為了完成某一個(gè)步驟,而是描述某個(gè)事務(wù)在解決問題的步驟中的行為。
對(duì)象是面向?qū)ο蠹夹g(shù)的核心所在,面向?qū)ο蠹夹g(shù)中的對(duì)象就是現(xiàn)實(shí)世界中某個(gè)具體的物理實(shí)體在計(jì)算機(jī)邏輯中的映射和體現(xiàn)。
面向過程和面向?qū)ο蟮膬?yōu)缺點(diǎn)及用途
總結(jié):
- 類是一組相關(guān)的 屬性(變量) 和 行為(方法) 的集合。是一個(gè)抽象概念設(shè)計(jì)的產(chǎn)物。
- 對(duì)象是該類事物的具體表現(xiàn)形式。具體存在的實(shí)體。
- 成員變量是對(duì)象的屬性(可以使變量、指針、數(shù)組等),屬性的值確定對(duì)象的狀態(tài)。
- 成員函數(shù)是對(duì)象的方法,確定對(duì)象的行為。
狀態(tài)和行為是對(duì)象的主要屬性
對(duì)象的狀態(tài)又稱為對(duì)象的靜態(tài)屬性,主要指對(duì)象內(nèi)部所包含的各種信息,也就是變量。每個(gè)對(duì)象個(gè)體都有自己專有的內(nèi)部變量,這些變量的值標(biāo)明了對(duì)象所處的狀態(tài)。
對(duì)象的方法(行為)一方面把對(duì)象的內(nèi)部變量包裹,封裝,保護(hù)起來(lái),使得只有對(duì)象自己的方法才能操作這些內(nèi)部變量,另一方面,對(duì)象的方法還是對(duì)象與外部環(huán)境和其他對(duì)象交互,通信的接口,對(duì)象的環(huán)境和其他對(duì)象可以通過這個(gè)接口來(lái)調(diào)用對(duì)象的方法,操縱對(duì)象的行為和改變對(duì)象的狀態(tài)。
對(duì)象是現(xiàn)實(shí)世界的實(shí)體或概念在計(jì)算機(jī)邏輯中的抽象表示。具體地,對(duì)象是具有唯一對(duì)象名和固定對(duì)外界接口的一組屬性和操作的集合,用來(lái)模擬或影響現(xiàn)實(shí)世界問題的一個(gè)或一組因素。
相對(duì)于傳統(tǒng)的面向過程的程序設(shè)計(jì)方法,而面向?qū)ο蟮某绦蛟O(shè)計(jì)具有的優(yōu)點(diǎn)
對(duì)象的數(shù)據(jù)封裝特性徹底消除了傳統(tǒng)結(jié)構(gòu)方法中數(shù)據(jù)與操作分離所帶來(lái)的種種問題,提高了程序的可復(fù)性和可維護(hù)性,降低了程序員保持?jǐn)?shù)據(jù)與操作相容的負(fù)擔(dān)。
對(duì)象的數(shù)據(jù)封裝特性還可以把對(duì)象的私有數(shù)據(jù)和公共數(shù)據(jù)分離開,保護(hù)了私有數(shù)據(jù),減少了可能的模塊間干擾,達(dá)到降低程序復(fù)雜性,提高可控性的目的。
對(duì)象作為獨(dú)立的整體具有良好的自恰性,即它可以通過自身定義的操作來(lái)管理自己。一個(gè)對(duì)象的操作可以完成兩類功能,一是修改自身的狀態(tài),二是向外界發(fā)布消息。
在具有自恰性的同時(shí),對(duì)象通過一定的接口和相應(yīng)的消息機(jī)制與外界聯(lián)系。這個(gè)特性與對(duì)象的封裝性結(jié)合在一起,較好地實(shí)現(xiàn)了信息的隱藏。
通過繼承可以很方便地實(shí)現(xiàn)應(yīng)用的擴(kuò)展和已有代碼的重復(fù)使用。
總結(jié):
面向?qū)ο蟪绦蛟O(shè)計(jì)是將數(shù)據(jù)及數(shù)據(jù)的操作封裝在一起,成為一個(gè)不可分割的整體,同時(shí)將具有相同特性的實(shí)體抽象成為一種新的數(shù)據(jù)類型—類。通過對(duì)象間的消息傳遞是整個(gè)系統(tǒng)運(yùn)轉(zhuǎn)。
類和對(duì)象關(guān)系和理解
類:一組相關(guān)的屬性和行為的集合,是一個(gè)抽象的概念。
對(duì)象:該類事務(wù)的具體表現(xiàn)形式,具體存在的個(gè)體。
上面這幾個(gè)概念,應(yīng)該怎么理解的呢?
類就是對(duì)一些具有共性特征,并且行為相似的個(gè)體的描述。
比如小楊和小秦都有姓名、年齡、身高、體重等一些屬性,并且兩人都能夠進(jìn)行聊天、運(yùn)動(dòng)等相似的行為。
由于這兩個(gè)人具有這些共性的地方,所以我們就把它抽象出來(lái),定義為一個(gè)類—人類,而小楊、小秦正是這個(gè)類中的個(gè)體,而每一個(gè)個(gè)體才是真正的具體的存在,光提到人類,你只知道應(yīng)該有哪些屬性行為,但你不知道他具體的一些屬性值。比如你知道他屬于“人類”,所以他應(yīng)該擁有姓名,年齡等屬性,但你并不知道他具體叫什么,年齡多大了。而小楊和小秦這兩個(gè)具體的對(duì)象,卻能夠?qū)崒?shí)在在的知道小楊今年23歲了,體重80kg等值。
總結(jié):
類是對(duì)象的抽象,而對(duì)象是類的具體實(shí)例。類是抽象的,不占用內(nèi)存,而根據(jù)類實(shí)例化具體的對(duì)象,就需要占用內(nèi)存空間了。
面向?qū)ο蟮娜笾饕卣?/strong>
封裝
常見的兩層含義 :一是把對(duì)象的屬性和行為看成一個(gè)密不可分的整體,將這兩者“封裝”在一個(gè)不可分割的獨(dú)立單元中;另一個(gè)是指“ 信息隱藏 ”,把不需要讓外界知道的信息隱藏起來(lái),有些對(duì)象的屬性及行為允許外界用戶知道或使用,但不允許更改,而另一些屬性或行為,則不允許外界知曉,或只允許使用對(duì)象的功能,而盡可能隱藏對(duì)象的功能實(shí)現(xiàn)細(xì)節(jié)。
封裝的好處:
- 可以對(duì)成員變量進(jìn)行更精確的控制。
- 類內(nèi)部的結(jié)構(gòu)可以自由修改。
- 好的封裝能夠減少耦合,符合程序設(shè)計(jì)“高內(nèi)聚,低耦合”。
- 隱藏實(shí)現(xiàn)細(xì)節(jié)。
- 提供公共的訪問方式。
- 提高代碼的復(fù)用性。
- 提高安全性。
繼承
繼承時(shí)面向?qū)ο?a target="_blank">編程技術(shù)的一塊基石,因?yàn)樗试S創(chuàng)建分等級(jí)層次的類。
繼承就是在一個(gè)已有類的基礎(chǔ)上派生出新類(例如動(dòng)物類可以派生出狗類和貓類),子類繼承父類的特征和行為,使得子類對(duì)象(實(shí)例)具有父類的實(shí)例域和方法,或子類從父類繼承方法,使得子類具有父類相同的行為。
繼承的好處:
- 提高代碼的維護(hù)性。
- 提高類代碼的復(fù)用性。
- 使得類和類產(chǎn)生了關(guān)系,是多態(tài)的前提(是繼承的一個(gè)弊端,讓類的耦合性增強(qiáng)了)。
**繼承概念的實(shí)現(xiàn)方式有三類:實(shí)現(xiàn)繼承、接口繼承、可視繼承
**
實(shí)現(xiàn)繼承:使用基類的屬性和方法而無(wú)序額外編碼的能力。
接口繼承:僅使用屬性和方法的名稱,但是子類必須提供實(shí)現(xiàn)的能力。
可視繼承:子窗體使用基窗體的外觀和實(shí)現(xiàn)代碼的能力。
繼承的特點(diǎn):
- 子類擁有父類非private的屬性,方法。
- 子類可以擁有自己的屬性和方法,即子類可以對(duì)父類進(jìn)行擴(kuò)展。
- 子類可以用自己的方式實(shí)現(xiàn)父類的方法,即重寫父類方法。
- 提高了類之間的耦合性。
訪問權(quán)限修飾符public、 protected 、private:
多態(tài)
多態(tài)是同一個(gè)行為具有多個(gè)不同表現(xiàn)形式或形態(tài)的能力,例如:黑白打印機(jī)和彩色打印機(jī)相同的打印行為卻有著不同的打印效果。
- 對(duì)象類型和引用類型之間存在著繼承(類)/ 實(shí)現(xiàn)(接口)的關(guān)系。
- 當(dāng)使用多態(tài)方式調(diào)用方法時(shí),首先檢查父類中是否有該方法,如果沒有,則編譯錯(cuò)誤;如果有,再去調(diào)用子類的同名方法。
- 如果子類重寫了父類的方法,最終執(zhí)行的是子類覆蓋的方法,如果沒有則執(zhí)行的是父類的方法。
多態(tài)的實(shí)現(xiàn): 靜態(tài)多態(tài)和動(dòng)態(tài)多態(tài)
靜態(tài)多態(tài):通過函數(shù)重載和模板來(lái)實(shí)現(xiàn),是在編譯期間確定,也稱早起綁定。
動(dòng)態(tài)多態(tài):通過虛函數(shù)和繼承來(lái)實(shí)現(xiàn),是在運(yùn)行期確定,也稱晚期綁定(動(dòng)態(tài)綁定)。
動(dòng)態(tài)多態(tài)的實(shí)現(xiàn):
當(dāng)編譯器發(fā)現(xiàn)類中有虛函數(shù)時(shí),會(huì)創(chuàng)建一張?zhí)摵瘮?shù)表,把虛函數(shù)的函數(shù)入口地址放到虛函數(shù)表中,并且在對(duì)象中增加一個(gè)指針vptr,用于指向類的虛函數(shù)表。當(dāng)派生類覆蓋基類的虛函數(shù)時(shí),會(huì)將虛函數(shù)表中對(duì)應(yīng)的指針進(jìn)行替換,從而調(diào)用派生類中覆蓋后的虛函數(shù),從而實(shí)現(xiàn)動(dòng)態(tài)綁定。
虛表:虛表中放置的是虛函數(shù)的入口地址,如果能拿到虛表中的內(nèi)容,即拿到了虛函數(shù)的入口地址,則可以將該函數(shù)調(diào)用起來(lái)。
基類虛表構(gòu)建過程 :編譯期間在編譯期間,按照虛函數(shù)在類中聲明的先后次序依次添加到虛表中。
派生類虛表的構(gòu)建過程 :
- 將基類虛表中內(nèi)容拷貝一份放置到子類虛表中。
- 如果子類重寫了基類的某個(gè)虛函數(shù),則使用子類自己的虛函數(shù)替換相同偏移量位置的基類虛函數(shù)地址。
- 對(duì)于子類新增的虛函數(shù),按照在類中聲明次序,依次放在虛表的后面。
函數(shù)重載、重寫、同名隱藏的對(duì)比:
函數(shù)重載:兩個(gè)或多個(gè)函數(shù)在同一作用域,函數(shù)名相同、參數(shù)列表不同。
重寫:兩個(gè)函數(shù)分別在基類和派生類的作用域中,函數(shù)名、參數(shù)、返回值類型都必須相同,基類虛函數(shù)必須為虛函數(shù),派生類函數(shù)最好也為虛函數(shù)。
同名隱藏:兩個(gè)函數(shù)分別在基類和派生類的作用域中,函數(shù)名相同,基類和派生類同名函數(shù)不是重寫就是同名隱藏。
多態(tài)的優(yōu)點(diǎn):
消除類型之間的耦合關(guān)系、可替換性、可擴(kuò)充性、接口性、靈活性、簡(jiǎn)化性。
動(dòng)態(tài)多態(tài)的作用:
- 隱藏實(shí)現(xiàn)細(xì)節(jié),使代碼模塊化,提高代碼的可復(fù)用性。
- 接口重用,使派生類的功能可以被基類的指針/引用所調(diào)用,即向后兼容,提高代碼的可擴(kuò)充性和可維護(hù)性。
動(dòng)態(tài)多態(tài)的必****要條件:繼承、虛函數(shù)覆蓋、基類指針/引用指向子類對(duì)象。
總之,C++多態(tài)的核心,就是用一個(gè)更通用的基類指針指向不同的子類實(shí)例,為了能調(diào)用正確的方法,我們需要用到虛函數(shù)和虛繼承。在內(nèi)存中,通過虛函數(shù)表來(lái)實(shí)現(xiàn)子類方法的正確調(diào)用;通過虛基類指針,僅保留一份基類的內(nèi)存結(jié)構(gòu),避免沖突。
面向?qū)ο蟮奈宕笤瓌t
** 單一職責(zé)原則SRP** (Single Responsibility Principle):是指 一個(gè)類的功能要單一,不能包羅萬(wàn)象 。如同一個(gè)人一樣,分配的工作不能太多,否則一天到晚雖然忙忙碌碌的,但效率卻高不起來(lái)。
**開放封閉原則OCP** (Open-Close Principle):一 個(gè)模塊在擴(kuò)展性方面應(yīng)該是開放的而在更改性方面應(yīng)該是封閉的 。比如:一個(gè)網(wǎng)絡(luò)模塊,原來(lái)只服務(wù)端功能,而現(xiàn)在要加入客戶端功能,那么應(yīng)當(dāng)在不用修改服務(wù)端功能代碼的前提下,就能夠增加客戶端功能的實(shí)現(xiàn)代碼,這要求在設(shè)計(jì)之初,就應(yīng)當(dāng)將服務(wù)端和客戶端分開,公共部分抽象出來(lái)。
** 里式替換原則LSP** (the Liskov Substitution Principle LSP): 子類應(yīng)當(dāng)可以替換父類并出現(xiàn)在父類能夠出現(xiàn)的任何地方 。比如:公司搞年度晚會(huì),所有員工可以參加抽獎(jiǎng),那么不管是老員工還是新員工,也不管是總部員工還是外派員工,都應(yīng)當(dāng)可以參加抽獎(jiǎng),否則這公司就不和諧了。
**依賴倒置原則DIP** (the Dependency Inversion Principle DIP): 高層模塊(穩(wěn)定)不應(yīng)該依賴低層模塊(變換)都應(yīng)該依賴于抽象(穩(wěn)定)。 抽象(穩(wěn)定)不應(yīng)該依賴于實(shí)現(xiàn)細(xì)節(jié)(變化),實(shí)現(xiàn)細(xì)節(jié)(變化)應(yīng)該依賴于抽象(穩(wěn)定) 。假設(shè)B是較A低的模塊,但B需要使用到A的功能,這個(gè)時(shí)候,B不應(yīng)當(dāng)直接使用A中的具體類:而應(yīng)當(dāng)由B定義一抽象接口,并由A來(lái)實(shí)現(xiàn)這個(gè)抽象接口,B只使用這個(gè)抽象接口:這樣就達(dá)到了依賴倒置的目的,B也解除了對(duì)A的依賴,反過來(lái)是A依賴于B定義的抽象接口。通過上層模塊難以避免依賴下層模塊,假如B也直接依賴A的實(shí)現(xiàn),那么就可能 造成循環(huán)依賴。一個(gè)常見的問題就是編譯A模塊時(shí)需要直接包含到B模塊的cpp文件,而編譯B時(shí)同樣要直接包含到A的cpp文件。
**接口分離原則ISP** (the Interface Segregation Principle ISP): 模塊間要通過抽象接口隔離開 ,而不是通過具體的類強(qiáng)耦合起來(lái)。
-
編程
+關(guān)注
關(guān)注
88文章
3634瀏覽量
93861 -
面向?qū)ο?/span>
+關(guān)注
關(guān)注
0文章
64瀏覽量
9994 -
面向過程
+關(guān)注
關(guān)注
0文章
2瀏覽量
5824
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論