




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、精選優(yōu)質文檔-傾情為你奉上C+基礎之面向對象編程思想(一)2011-07-14 17:24 佚名 互聯網 字號: | 本文介紹的是以C+程序語言為基礎的面向對象的編程思想。希望對你有幫助,一起來看吧!AD: 我們都知道,C+中最重要的概念類,了解了類之后,已經可以開始做些編程方面比較高級的應用設計程序,而不再只是將算法變成代碼。要說明如何設計程序,有必要先了解何謂編程思想。建議大家閱讀這一系列的文章,供大家參考。· · · 編程思想編程,即編寫程序,而之前已經說過,程序就是方法的描述,那么編程就是編寫方法的描述。我知道如何到人民公園,然后我就編寫了到人民公園的方法
2、的描述 從市中心開始向東走400米再向右轉走200米就是。接著另一個人也知道如何去,但他編的程序卻是從市中心沿人民東路走過兩個交叉口,在第三個交叉口處右轉,直走就能在右手方看到。很明顯,兩個程序不同,但最后走的路線是相同的,即大家的方法相同,但描述不同。所謂的編程思想,就是如何編程,即編寫程序的方法。這也是為什么不同的人對同一算法編寫出的程序不同(指程序邏輯,不是簡單的變量或函數名不同),不同的人的編程思想不同。如果多編或多看一些程序,就會發(fā)現編程思想是很重要的。好的編程思想編出的程序條理分明,可維護性高;差的編程思想編出的程序晦澀難懂,可維護性低。注意,這里是從程序的易讀性來比較的,實際出于
3、效率,是會使用不符合人腦思維習慣的編程思想,進而導致代碼的難于維護,但為了效率還是會經常在程序的瓶頸位置使用被優(yōu)化了的代碼(這種代碼一般使用匯編語言編寫,算法則很大程度上是數學上的優(yōu)化,丟棄了大部分其在人類世界中的意義)。本系列一直堅持并推薦這么一個編程思想一切均按照語義來編寫。而語義是語言的意義,之前說它是代碼在人類世界中的意義。比如桌子,映射成一個結構,有桌腳數、顏色等成員變量,那么為什么沒有質量、材料、價格、生產日期等成員?對此有必要說明一下“人類世界”的含義。世界我們生活在一個四維的客觀物理世界中,游戲中的怪物生活在游戲定義的游戲世界中,白雪公主生活在一個童話世界中。什么叫世界?世界即
4、規(guī)則的集合。比如客觀世界中,力可作用于有質量的物體上,并進而按照運動學定律改變物體的速度;電荷異性相吸同性相斥;能量守恒等,這些都是對客觀世界這個規(guī)則的集合中的某些規(guī)則的描述。注意它們都只是規(guī)則的描述,不是規(guī)則,就好像程序是方法的描述,但不是方法。即方法和規(guī)則都是抽象的邏輯概念,各自通過程序和論調來表現。程序就是我們要編寫的,而論調就是一門理論,如概率論、運動學、流體力學等。而前面所說的游戲世界,是因為游戲也是一系列規(guī)則。同樣,童話世界也是由一系列的規(guī)則組成。如白雪公主能吃東西,能睡覺,并且能因為吃了毒蘋果而中毒;魔鏡能回答問題等。那么就算了解了世界這個概念又怎樣?有什么用?前面說了本系列是推
5、薦按照語義來編寫程序。而算法是基于某些規(guī)則的,如給出1到100求和的算法是(1+100)*100/2,這里就暗示已經有那么些規(guī)則說明什么是加減乘除,什么是求和。即一個算法一定是就一個世界來說的,它在另一個世界可能毫無意義。因為算法就是方法,是由之前說的命令和被操作的資源組成,而命令和資源就是由世界來定義的。前面說根據算法寫代碼,其實是先制訂了一個世界來做為算法展示的平臺。如之前的商人過河,其就在如下的一個規(guī)則集上表現的:有一只能坐兩人的船可以載人過河;有三個商人和三個仆人在河的一邊;河的任意一邊仆人數多過商人數商人就會被殺。這是對過河問題所基于的世界的嚴重不準確的描述,但在這過于抽象并沒什么好
6、處,只用注意:上面的商人和仆人不是現實世界中的商人和仆人,他們不能吃飯不能睡覺不能講話,甚至連走路都不會,唯一會的是通過坐船過河來改變自身的位置。當某一位置(即河的某一岸)的仆人的實例多于商人的實例時(且商人的實例至少有一個),則稱商人被殺。上面的描述暫且稱為商人仆人論,它是對過河問題所基于的世界的一個描述。另一個人卻不像上面那樣看待問題。河有兩個岸,每個河岸總對應著兩個數字商人數和仆人數。有一個途徑能按照某個規(guī)則改變河岸對應的兩個數字(就是坐只能坐兩人的船過河),而當任何一個河岸所對應的仆人數多于商人數時(且商人數不為零),則稱商人被殺。此人沒有定義商人和仆人這么兩個概念,而只定義了一個概念
7、河岸,此概念具有兩個屬性商人數和仆人數。這是另一個論調,暫且稱為河岸論。什么意思?上面就是對商人過河問題所基于的世界的兩個不同論調。注意上面論調不同,但描述的都是同一個世界,就好像動力學和量子力學,都是對客觀世界物體之間作用規(guī)則的描述,但大相徑庭。算法總是基于一個世界,但更準確點的說法應是算法總是基于一個世界的描述,而所謂的設計程序就是編寫算法所基于的世界描述,即論調,而論調其實就是問題的描述。現在考慮前面說的商人仆人論和河岸論,它們都是同一世界的描述,但前者提出兩個名詞性概念商人和仆人,各自具有“位置”這個狀態(tài)和“坐船”這么一個功能以及“商人被殺”這個動詞性概念;后者提出一個名詞性概念河岸,
8、具有“商人數”和“仆人數”兩個屬性和“商人被殺”及“坐船”兩個動詞性概念。在此,說后者比前者好,因為后者定義的名詞性概念更少(即名詞性概念比動詞性概念更容易增加架構的復雜性,因為其代表了世界中東西的種類,種類越繁多則世界越復雜,越難以實現),雖說不一定更容易理解,但結構更簡單。易發(fā)現,所有的論調都可以只由“名詞性概念”和“動詞性概念”組成,其中前者在數學中就是數、實數、復數等,后者是加減乘除、求導等,它們都被稱作定義。在游戲論中,我將前者稱為類,而類的實例就是方法中被操作的的資源,后者稱為命令。而在方法中,前者是資源的類型,后者是操作的類型。一個論調,提出的概念越少,結構就越簡單,也就越好。但
9、應注意,就電腦編程來說,由于電腦并不是抽象的概念,而是存在效率因素的,因此基于前述的好的論調的算法而編出的代碼的運行效率并不一定高。因此,所謂的程序設計,就是設計算法所基于的論調,而好的程序設計,就是相應的論調設計得好。但前面說了,效率并不一定高,對此,一般僅在代碼的瓶頸位置另外設計,而程序的整體架構依舊按照之前的設計。隨著程序的日趨龐大,清晰簡明的程序架構越顯重要,而要保持程序架構的簡明,就應設計好的論調;要保持架構的清晰,就應按照語義來編寫代碼。下面,介紹如此風靡的面向對象編程思想來幫助設計程序。何謂對象要說明面向對象,首先應了解何謂對象。對象就是前述的“名詞性概念”的實現,即一個實例。如
10、商人仆人論中有商人和仆人兩個“名詞性概念”,其有三個商人和三個仆人,則稱有六個對象,分別是三個商人的實例和三個仆人的實例。應注意對象和實例的區(qū)別,其實它們沒有區(qū)別,如果非要說區(qū)別,可以認為對象能夠沒有狀態(tài),但實例一定有狀態(tài)。那么什么叫狀態(tài)?還是先來看看什么叫屬性。桌子有個屬性叫顏色,這張桌子是紅色的而那張是綠的。人有個狀態(tài)叫臉色,這個人的臉色紅潤而那個的慘白。都是顏色,但一個是屬性一個是狀態(tài),什么區(qū)別?如果把桌子和人都映射成類,那么桌子的顏色和人的臉色都應映射成相應類的成員變量,而兩者的區(qū)別就是桌子的實例在主要運作過程中顏色都不變化,其主要用于讀;人的臉色在人的實例的主要運作過程中可能變化,其
11、主要用于寫。什么叫運作過程?類映射的是資源,資源可以具有功能,即成員函數,當一個實例的功能執(zhí)行時,就是這個實例的運作過程。桌子有個功能是“放東西”,當調用這個成員函數時,其中會讀取顏色這個屬性的值以判斷放在桌子上的東西的顏色是否和桌子的顏色搭配協(xié)調。人有個功能是“泡澡”,其可以使相應實例的臉色從慘白向紅潤轉變。但桌子也有個功能是“改變顏色”,調用它可以改變桌子的顏色。按照前面所說,顏色是屬性,應該被讀,但這里卻在實例的運作過程中對它進行了寫操作。注意前面說的是“主要運作過程”,即桌子的目的是用來“放東西”,不是“改變顏色”。如果桌子這個概念在其相應世界中主要是用來改變其顏色而不是放東西,此時桌
12、子只不過是一個能記錄顏色值的容器,而這時桌子的顏色就是狀態(tài),不是屬性了。有何意義?屬性和狀態(tài)都映射為成員變量,從代碼上是看不出它們的區(qū)別的,但它們的語義是有嚴重區(qū)別的。屬性是用來配置實例而狀態(tài)是用來表現實例。在面向對象編程思想中,只是簡單地說對象是具有屬性和功能(也被稱作方法)的實例,這在編寫的程序所基于的世界比較復雜時顯得非常地孱弱,而且就是對“屬性”的錯誤理解,再加上“封裝”這個詞匯的席卷,導致出現大量的荒謬代碼,后面說明。屬性和狀態(tài)的差別導致出現所謂的無狀態(tài)對象(在MTSMicrosoft Transaction Server中提出,稱作Stateless Component,無狀態(tài)組件
13、),這正是對象和實例的差別對象是實現,因此可以是一個抽象概念的實現;實例是實際存在,不能是抽象概念的實現。這在 C+代碼上就表現為沒有成員變量的類和有成員變量的類。如下:1. struct Search virtual int search( int*, int, int ); 2. Search a, b; int c3 = 10, 20, 5 a.search(&
14、#160;c, 3, 20 ); 這里就生成兩個對象a和b,它們都是抽象概念搜索功能的對象。注意結構Search沒有成員變量,因為不需要,那么a和b的長度是多少?由于可能出現下面的情況,一般的編譯器都將上面的a和b的長度定為一個字節(jié),進而&a就不等于&b。1. struct BSearch : public Search int search( int*, int, int ); 2. Search
15、60;*p; BSearch d; p = &a; p = &b; p = &d; p->search( c, 3, 5 ); 注意從代碼上依舊可以稱上面生成了Search的兩個實例a和b,BSearch的一個實例d(即使實際上它們根本不存在,邏輯上大小為零),這也就是為什么之前說它和對象沒有區(qū)別,僅僅有概念上的微小差別。應注意前面提到的無狀態(tài)對象并不是說沒有成員變量的類的實例,只是沒狀態(tài),并不代
16、表沒有屬性。如前面的BSearch可能有個屬性 m_MaxSearchTimes以表示折半搜索時如果搜索m_MaxSearchTimes那么多次仍沒找到,則BSearch:search返回沒找到。雖然這里BSearch有了成員變量,但就邏輯上它還是一個抽象概念。由于屬性和狀態(tài)的實現相同(都通過成員變量),因此要實現無狀態(tài)對象需要一些特殊手段,由于與本系列無關,在此不表。前面的a和b有區(qū)別嗎?為什么要有兩個實例?“搜索功能”按照之前說的語義不是更應該映射為函數?為什么要映射成沒有成員變量的類?上面的用法在 STL(Standard Template Library標準模版庫)中被使用,做了一些變
17、形,稱作函數類,是一種編程技巧。但的確有這種語義查找功能有三個參數:查找條件、查找位置(即欲搜索的容器或集合)、查找前排序容器或集合的方法。這里傳遞函數指針不是剛剛好嗎(實際并不剛剛好,指針的語義是引用,在這并不很準確)?這就是所謂的面向對象編程思想。C+基礎之面向對象編程思想(二)2011-07-14 17:37 佚名 互聯網 字號: | 本文介紹的是以C+程序語言為基礎的面向對象的編程思想。希望對你有幫助,一起來看吧!AD: 我們都知道,C+中最重要的概念類,了解了類之后,已經可以開始做些編程方面比較高級的應用設計程序,而不再只是將算法變成代碼。要說明如何設計程序,有必要先了解何謂面向對象
18、編程思想。建議大家閱讀這一系列的文章,供大家參考。面向對象編程思想前面已說明設計程序就是編寫程序欲解決的問題的描述,也就是編寫論調。而論調可以只用“名詞性概念”和“動詞性概念”表現出來,對象又正好是“名詞性概念”的實現,而利用前面說的沒有成員變量的類來映射“動詞性概念”就可以將其轉換為對象。因此,一個世界,可以完全由對象組成,而將算法所基于的世界只用對象表現出來,再進行后續(xù)代碼的編寫,這種編程方法就被稱作面向對象的編程思想。注意,先設計算法應基于的世界,再全部用對象將其表述出來,然后再設計算法,最后映射為代碼。但前面在編寫商人過河問題時是直接給出算法的,并沒有設計世界???其實由于那個問題的過于
19、簡單,我直接下意識地設計了世界,并且用前面所說的河岸論來描述它。應注意世界的設計完全依賴于問題,而準確地說,前面我并沒有設計世界,而是設計了河岸論來描述問題。接著,由于對象就是實例,因此以對象來描述世界在C+中就是設計類,通過類的實例來組合表現世界。但應注意,面向對象是以對象來描述世界,但也描述算法,因為算法也會提出一些需要被映射的概念,如前面商人過河問題的算法中的過河方案。但切記,當描述算法時操作了描述世界時定義的類,則一定要保持那個類的設計,不要因為算法中對那個類的實例的操作過于復雜而將那部分算法映射為這個類的一個成員函數,因為這嚴重遮蔽了算法的實現,破壞了程序的架構。如一個算法是讓汽車原
20、地不停打轉,需要復雜的操作,那么難道給汽車加一個功能,讓它能原地不停地打轉?!這是在設計類的時候經常犯的錯誤,也由于這個原因,一個面向對象編寫的代碼并不是想象的只由類組成,其也可能由于將算法中的某些操作映射成函數而有大量的全局函數。請記?。涸O計類時,如果是映射世界里的概念,不要考慮算法,只以這個世界為邊界來設計它,不要因為算法里的某個需要而給它加上錯誤的成員。因此,將“名詞性概念”映射成類,“名詞性概念”的屬性和狀態(tài)映射為成員變量,“名詞性概念”的功能映射為成員函數。那么“動詞性概念”怎么辦?映射成沒有成員變量的類?前面也看見,由于過于別扭,實際中這種做法并不常見(STL中也只是將其作為一種技
21、巧),故經常是將它映射為函數,雖然這有背于面向對象的思想,但要易于理解得多,進而程序的架構要簡明得多。隨著面向對象編程思想的問世,一種全新的設計方式誕生了。由于它是如此的好以至于廣為流傳,但理解的錯誤導致錯誤的思想遍地而生,更糟糕的就是本末倒置,將這個設計方式稱作面向對象的編程思想,它的名字就是封裝。封裝先來看現在在各類VC教程中關于對象的講解中經常能看見的如下的一個類的設計。1. class Person 2. private: char m_Name20; unsigned long m_Age;
22、;bool m_Sex; 3. public: const char* GetName() const; void SetName( const char* ); 4. unsigned long GetAge() const; void SetAge( unsigned long ); 5. bool GetSex() const; void
23、0;SetSex( bool ); 6. 上面將成員變量全部定義為private,然后又提供三對Get/Set函數來存取上面的三個成員變量(因為它們是private,外界不能直接存?。?,這三對函數都是public的,為什么要這樣?那些教材將此稱作封裝,是對類Person的內部內存布局的封裝,這樣外界就不知道其在內存上是如何布局的并進而可以保證內存的有效性(只由類自身操作其實例)。首先要確認上面設計的荒謬性,它是正宗的“有門沒鎖”毫無意義。接著再看所謂的對內存布局的封裝。假設上面是在Person.h中的聲明,然后在b.cpp中要使用類Per
24、son,本來要#include "Person.h",現在替換成下面:1. class Person 2. public: char m_Name20; unsigned long m_Age; bool m_Sex; 3. public: const char* GetName() const; void SetName( const char* ); 4.
25、 unsigned long GetAge() const; void SetAge( unsigned long ); 5. bool GetSex() const; void SetSex( bool ); 6. 然后在b.cpp中照常使用類Person,如下:1. Person a, b; a.m_Age = 20; b.GetSex();
26、160;這里就直接使用了Person:m_Age了,就算不做這樣蹩腳的動作,依舊#include "Person.h",如下:1. struct PERSON char m_Name20; unsigned long m_Age; bool m_Sex; 2. Person a, b; PERSON *pP = ( PERSON* )&a; pP->m_Ag
27、e = 40; 上面依舊直接修改了Person的實例a的成員Person:m_Age,如何能隱藏內存布局?!請回想聲明的作用,類的內存布局是編譯器生成對象時必須的,根本不能對任何使用對象的代碼隱藏有關對象實現的任何東西,否則編譯器無法編譯相應的代碼。那么從語義上來看。Person映射的不是真實世界中的人的概念,應該是存放某個數據庫中的某個記錄人員信息的表中的記錄的緩沖區(qū),那么緩沖區(qū)應該具備那三對Get/Set所代表的功能嗎?緩沖區(qū)是緩沖數據用的,緩沖后被其它操作使用,就好像箱子,只是放東西用。故上面的三對Get/Set沒有存在的必要,而三個成員變量則不能是 pri
28、vate。當然,如果Person映射的并不是緩沖區(qū),而在其它的世界中具備像上面那樣表現的語義,則像上面那樣定義就沒有問題,但如果是因為對內存布局的封裝而那樣定義類則是大錯特錯的。上面錯誤的根本在于沒有理解何謂封裝。為了說明封裝,先看下MFC(Microsoft Foundation Class Library微軟功能類庫,一個定義了許多類的庫文件,其中的絕大部分類是封裝設計。關于庫文件在說明SDK時闡述)中的類CFile的定義。從名字就可看出它映射的是操作系統(tǒng)中文件的概念,但它卻有這樣的成員函數CFile:Open、CFile:Close、CFile:Read、 CFile:Write,有什么
29、問題?這四個成員函數映射的都是對文件的操作而不是文件所具備的功能,分別為打開文件、關閉文件、從文件讀數據、向文件寫數據。這不是和前面說的成員函數的語義相背嗎?上面四個操作有個共性,都是施加于文件這個資源上的操作,可以將它們叫做“被功能”,如文件具有“被打開”的功能,具有“被讀取”的功能,但應注意它們實際并不是文件的功能。按照原來的說法,應該將文件映射為一個結構,如FILE,然后上面的四個操作應映射成四個函數,再利用名字空間的功能,如下:1. namespace OFILE 2. 3. bool Open( FILE&, &
30、#160;); bool Close( FILE&, ); 4. bool Read( FILE&, ); bool Write( FILE&, ); 5. 上面的名字空間OFILE表示里面的四個函數都是對文件的操作,但四個函數都帶有一個FILE&的參數?;叵敕庆o態(tài)成員函數都有個隱藏的參數this,因此,一個了不起的想法誕生了。將所有對某種資源的操作的集合看成是一種資源,把它映射成一個類,則這個類的對象就是對某個對象的操作,此法被稱作封裝,而那個類被稱作包裝類或封裝類。很明顯,包裝類映射的是“對某種資源的操作”,是一抽象概念,即包裝類的對象都是無狀態(tài)對象(指邏輯上應該是無狀態(tài)對象,但如果多個操作間有聯系,則還是可能有狀態(tài)的,但此時它的語義也相應地有些變化。如多一個CFile:Flush成員函數,用于刷新緩沖區(qū)內容,則此時就至少有一個狀態(tài)緩沖區(qū),還可有一個狀態(tài)記錄是否已經調用過CFile:Write,沒有則不用刷新)?,F在應能了解封
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 長期煤渣運輸合同協(xié)議
- 閉門器購買合同協(xié)議
- 陽臺落地窗安裝合同協(xié)議
- 門頭攤位出租合同協(xié)議
- 防撞梁安裝服務合同協(xié)議
- 集資合作協(xié)議合同模板
- 項目資金合作合同協(xié)議
- 鞋子出售代理合同協(xié)議
- 食堂員工聘用協(xié)議書模板
- 項目入股合作合同協(xié)議
- 09J202-1 坡屋面建筑構造(一)-1
- 《如何閱讀文獻》課件
- 本科《中醫(yī)美容學》教學大綱
- 2022年俄烏沖突戰(zhàn)爭PPT
- 機柜間主體施工方案
- 盂蘭盆供簡易儀軌
- 2019年上海市嘉定區(qū)高考英語一模試卷
- GB/T 3608-2008高處作業(yè)分級
- 2022年保德縣城污水處理有限公司招聘筆試試題及答案解析
- 薩提亞模式家庭治療課件
- 社會語言學 語言的性別、年齡變異課件
評論
0/150
提交評論