C++ 封裝 跟繼承關係 |
|
yshihyu
一般會員 發表:23 回覆:18 積分:8 註冊:2006-11-28 發送簡訊給我 |
|
Stallion
版主 發表:52 回覆:1600 積分:1995 註冊:2004-09-15 發送簡訊給我 |
|
aftcast
站務副站長 發表:81 回覆:1485 積分:1763 註冊:2002-11-21 發送簡訊給我 |
首先要了解這二個字的意義:
1/ 封裝,它的實作就是c 裡的類別。在c的時代,比較接近這功能的只有struct。物件導向之前,開發的流程通常是"程序"化的。舉個物件開發的例子,比如我們要寫一個"車子"的類別,那這個類別中我們會定義: 方向盤這個資料成員,輪子等…然後還有成員函式(方法),如"右轉","加油門"等…封裝的意思就是把這些「資料成員」與「方法」全都"封"在一個類別裡。相較過去的c語言來說,沒有好的封裝,所以function和variable都是散開的。簡單講封裝就是一種模組化! 2/ 繼承,它是為了程式可重複使用而來。比如想寫一個休旅車的類別,但之前就有一個"車子"的類別,你就可以使用繼承。只需在程式碼上多加一些休旅車的特性即可,無需在寫"方向盤"等… 想想,若是沒有封裝模組化,要如何的來把它繼承下來重複使用呢? ===================引 用 文 章=================== 我看C 書上提到 有封裝 才有繼承 , 有繼承才有多型 不過為什麼有封裝才有繼承?? 搞不懂 ??懂得朋友可以舉例說明嗎?? 謝謝
------
蕭沖 --All ideas are worthless unless implemented-- C++ Builder Delphi Taiwan G+ 社群 http://bit.ly/cbtaiwan |
yshihyu
一般會員 發表:23 回覆:18 積分:8 註冊:2006-11-28 發送簡訊給我 |
|
Stallion
版主 發表:52 回覆:1600 積分:1995 註冊:2004-09-15 發送簡訊給我 |
===================引 用 文 章===================
那就是說封裝是OO特性 , 跟繼承沒有直接關係是嗎?? 是的。封裝的好處就是保護類別的重要資料,改善以往程式的缺點。 那多型應該跟繼承有關係對嗎??? 沒繼承就沒有多型問題存在我這樣說對嗎?? 完全正確。 多型都是在指虛擬函式嗎??? 函式多載( 函式名稱相同參數有差異?)也能說是多型的一種嗎?? 多型不是在指虛擬函式,多型指的是子類別繼承父類別後產生的關係型態,而虛擬函式則屬於類別,虛擬函式主要為父類別提供給子類別Overload或Overwrite,以相同的函式名稱,做不同的功能需求;函式的多載是獨樹一格的,跟類別的多型不同,看原文就知道意思了。多型(Polymorphism),多載(Overload)。 |
yshihyu
一般會員 發表:23 回覆:18 積分:8 註冊:2006-11-28 發送簡訊給我 |
|
aftcast
站務副站長 發表:81 回覆:1485 積分:1763 註冊:2002-11-21 發送簡訊給我 |
sorry,再插個話…
1/ 多型是一種概念名詞,指的是當一堆元件彼此之間發生繼承關係後,該如何用同一個方法名稱來表達不同的結果。用文字說明你可能比較難理解。我用你形狀的例子 來說…三角形和三角錐形有著一些相同的屬性與方法,比如說二者都有一個叫draw的方法,因為三角錐繼承了三角形,所以三角錐也可以呼叫draw,可是當 你使用: 三角錐.draw( )時畫出來的並不是你想要的,它會畫出三角形而非錐形! 為了要讓draw這個方法正確的畫出子類別要的錐形,你必需"重寫"(override)draw這個方法,這樣就不會去呼叫父類的draw,而是自己的draw。 2/ 既然多型是一種"設計"概念名詞,那如何實現呢? 它使用「動態繫結」(binding)的"技術"概念來達成。簡單講就是compiler會偷建一個table來記錄何時該叫父類的draw,何時該叫子類的draw。 3/ 各語言實現動態繫結的語法都略有不同。在c 中,的確是用"虛擬函式"來達成,即在draw前面加一個virtual關鍵字。當父類中宣告了 virtual draw( ); 時即表示子類別可以自己建構同名的draw( ) 方法。另外,當宣告成virtual draw( ) = 0; 時,在c 裡就稱"純虛擬函式"(pure virtual function),即可以只宣告但無需在父類實作draw的內容。這在別的語言中通稱"介面"(interface)。 4/ is a ... (是一種…) 當 A is a B 時,表示A可以繼承B,比如說: 老虎是一種貓科動物。表示當你要寫老虎時,你可以直接繼承貓以省程式碼。你更可以透過介面來呼叫貓的一些方法… 5/ hsa a (擁有一種…),用例子說明較快。Human has a ear。人類有一個耳朵。當你在寫一個人類的類別時,你是要"繼承"一個耳朵類別還是在類別資料成員中定義一個耳朵的instance? 二種寫法都可以使耳朵的功能出現在人類的類別中。但用繼承的方式寫很怪,因為要考慮另一種"向上轉型"(upcast)的情形,也就是說,比子類別暫變成 父類。比如說: 三角錐向上轉成三角形,這沒問題,因為有共同三角的關係。但耳朵這個例子來看… 人類向上轉成耳朵? 人類是一種耳朵? 怪怪的吧… 不過,特別要注意,若不考慮upcast的完美現象,就類別的功能性來說,二種寫法都有耳朵可以操控。 我有一個blog有寫一些關於c 的一些深入概念,你也許也可以參考看看! 蕭沖 qs.xiao@gmail.com http://aftcast.blogspot.com/ --All ideals are worthless unless implemented--
------
蕭沖 --All ideas are worthless unless implemented-- C++ Builder Delphi Taiwan G+ 社群 http://bit.ly/cbtaiwan |
Coffee
版主 發表:31 回覆:878 積分:561 註冊:2006-11-15 發送簡訊給我 |
(亂入開始)
我還是喜歡用車子來說 車輛假設可以被定義成顏色、油量、出力、輪數等「屬性」 而車子可以被發動、加油、移動、加速、停止等等「方法」 而機車可以被定義為是一個繼承自車輛類別,只有兩輪的車輛, 轎車則是一個繼承自車輛,有四輪的車輛 這就是多型,而繼承的類別則是「專化」並窄化上層類別的定義,如上例,機車就只能有兩輪,轎車只能有四輪 我們都知道有例外,所以我們在定義我們要使用的類別的時候必須要注意這些問題 而我們希望車子是「可以被駕駛的」,也就是它必須要符合「發動」、「移動」、「控制方向」 於是我們定義「駕駛」必須要有這些行為,這就是所謂的介面, 它不去管誰來用這個介面,總之這個介面只負責這些行為,要用這個介面的人必須要依照這個介面的定義去撰寫這些行為 而車子發動的方法大多數都是用鑰匙,但是某些車子會提供不同的發動方式,比如說按按鍵,或者是語音發動 那麼我們就可以讓這個類別有function 發動(一個鑰匙);及function 發動();這個不用鑰匙的方法,這就是多載, 多載有什麼好處?因為同樣都是發動,我們只需要「發動」這個名詞就好, 當然也可以定義function 發動(一個鑰匙);及function發動_不用鑰匙();這樣的形式 但是同樣是發動,如果這是自己寫的函式還好解決,我們都知道在什麼時機下該去用這個函式 只是在描述的過程中,同樣是發動卻不是同一個詞,語意上不是很好 再者,如果這個類別交由別人去使用時,使用重載,我就只要查發動到底有哪些重載的形式,就知道這種車子有哪些可以被使用的發動方法 技術上來說,就如同上面的前輩說的使用binding的方法,實際上就是一個VMT(Virtual Method Table)來決定何時要呼叫何種函式, 所以函式多載在同一個類別必須要有不同的參數型態,否則VMT無法決定要使用哪一個函式 如果定義了function 發動();跟 function 發動();,那麼當你在發動車子的時候,VMT就不知道要使用哪一個了 而機車 is 車輛是成立的,因為機車是車輛衍生的類別,汽車 is 機車則不成立,雖然它們有同樣的上層,但它們的定義不同 而透過機車產生了一臺車子,這臺車子叫它小綿羊好了,小綿羊 is 機車也是成立的,因為小綿羊是用機車的定義產生的實體(Instance) 小綿羊 is not 汽車,小綿羊 is 車輛也是成立的 小綿羊 has 發動的方法,has 輪子數這些屬性 總之,小綿羊自己的東西,就叫作成員,管它是私有的公開的保護的 而小綿羊提供給我們的操作與資料就是屬性,如發動方法、或者是出力多少的屬性 只不過通常函式形態會被特指為method,而不是function或procedure,因為那是這個類別的「使用方法」 而顏色等提供資料的會被叫「屬性」(Attribute或Property) 我打了整整的兩遍啊...cookie啊..XDDDDDD
------
不論是否我發的文,在能力範圍皆很樂意為大家回答問題。 為了補我的能力不足之處,以及讓答案可以被重複的使用,希望大家能儘量以公開的方式問問題。 在引述到我的文時自然會儘量替各位想辦法,謝謝大家! |
yshihyu
一般會員 發表:23 回覆:18 積分:8 註冊:2006-11-28 發送簡訊給我 |
===================引 用 文 章=================== sorry,再插個話… 1/ 多型是一種概念名詞,指的是當一堆元件彼此之間發生繼承關係後,該如何用同一個方法名稱來表達不同的結果。用文字說明你可能比較難理解。我用你形狀的例子 來說…三角形和三角錐形有著一些相同的屬性與方法,比如說二者都有一個叫draw的方法,因為三角錐繼承了三角形,所以三角錐也可以呼叫draw,可是當 你使用: 三角錐.draw( )時畫出來的並不是你想要的,它會畫出三角形而非錐形! 為了要讓draw這個方法正確的畫出子類別要的錐形,你必需"重寫"(override)draw這個方法,這樣就不會去呼叫父類的draw,而是自己的draw。 2/ 既然多型是一種"設計"概念名詞,那如何實現呢? 它使用「動態繫結」(binding)的"技術"概念來達成。簡單講就是compiler會偷建一個table來記錄何時該叫父類的draw,何時該叫子類的draw。 3/ 各語言實現動態繫結的語法都略有不同。在c 中,的確是用"虛擬函式"來達成,即在draw前面加一個virtual關鍵字。當父類中宣告了 virtual draw( ); 時即表示子類別可以自己建構同名的draw( ) 方法。另外,當宣告成virtual draw( ) = 0; 時,在c 裡就稱"純虛擬函式"(pure virtual function),即可以只宣告但無需在父類實作draw的內容。這在別的語言中通稱"介面"(interface)。 4/ is a ... (是一種…) 當 A is a B 時,表示A可以繼承B,比如說: 老虎是一種貓科動物。表示當你要寫老虎時,你可以直接繼承貓以省程式碼。你更可以透過介面來呼叫貓的一些方法… 5/ hsa a (擁有一種…),用例子說明較快。Human has a ear。人類有一個耳朵。當你在寫一個人類的類別時,你是要"繼承"一個耳朵類別還是在類別資料成員中定義一個耳朵的instance? 二種寫法都可以使耳朵的功能出現在人類的類別中。但用繼承的方式寫很怪,因為要考慮另一種"向上轉型"(upcast)的情形,也就是說,比子類別暫變成 父類。比如說: 三角錐向上轉成三角形,這沒問題,因為有共同三角的關係。但耳朵這個例子來看… 人類向上轉成耳朵? 人類是一種耳朵? 怪怪的吧… 不過,特別要注意,若不考慮upcast的完美現象,就類別的功能性來說,二種寫法都有耳朵可以操控。 我有一個blog有寫一些關於c 的一些深入概念,你也許也可以參考看看! 蕭沖 qs.xiao@gmail.com http://aftcast.blogspot.com/ --All ideals are worthless unless implemented-- ____________________________________________________________________________________ 關於您提到向上轉型 , 我書上也有看到類似問題但不太明白 class Employee { private: char ame[40]; ... purblic: void show_name(); ...};class Singer : public Employee { ...purblic: void range(); ...};...Employee veep; Singer trala;Employee *pe = &trala; // 向上轉型 Singer *ps = (Singer*) &veep; // 向下轉型...ps->show_name(); // Singer 繼承Employee 安全操作 pe->range(); // 這樣算是不安全因為Employee 不一定有 range() 1 向上轉型在c 實作上都是安全的嗎??? 只是類別關係間如你所講的不完美現象 2 向下轉型是不是都存在不安全性 如果上面的pe->range(); 問題 , 是否有什麼解決的辦法避免 , 還是在處理向下轉型的時候在去注意?? 3 最後想知道在虛擬函式也有向上或向下轉型存在問題嗎?? 謝謝 |
暗黑破壞神
版主 發表:9 回覆:2301 積分:1627 註冊:2004-10-04 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |