全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:4959
推到 Plurk!
推到 Facebook!

C++ 封裝 跟繼承關係

 
yshihyu
一般會員


發表:23
回覆:18
積分:8
註冊:2006-11-28

發送簡訊給我
#1 引用回覆 回覆 發表時間:2006-12-30 02:50:40 IP:59.104.xxx.xxx 訂閱
我看C++ 書上提到 有封裝 才有繼承  , 有繼承才有多型
不過為什麼有封裝才有繼承?? 搞不懂 ??懂得朋友可以舉例說明嗎??
謝謝
Stallion
版主


發表:52
回覆:1600
積分:1995
註冊:2004-09-15

發送簡訊給我
#2 引用回覆 回覆 發表時間:2006-12-30 17:39:16 IP:211.22.xxx.xxx 未訂閱
封裝是OO的特性與設計要求,主要在保護類別中的重要資料不會輕易被改寫,除非經過類別的介面才得以存取,而繼承是OO得以號稱軟體IC的重要特性,利用已存在的類別加以繼承利用已存在被繼承類別中的方法減少開發時程,兩者之間是沒有絕對關連的!
===================引 用 文 章===================
我看C 書上提到 有封裝 才有繼承 , 有繼承才有多型
不過為什麼有封裝才有繼承?? 搞不懂 ??懂得朋友可以舉例說明嗎??
謝謝
aftcast
站務副站長


發表:81
回覆:1485
積分:1763
註冊:2002-11-21

發送簡訊給我
#3 引用回覆 回覆 發表時間:2006-12-30 21:29:21 IP:60.248.xxx.xxx 訂閱
首先要了解這二個字的意義:
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

發送簡訊給我
#4 引用回覆 回覆 發表時間:2006-12-31 08:31:39 IP:59.104.xxx.xxx 訂閱
to Stallion
那就是說封裝是OO特性 , 跟繼承沒有直接關係是嗎??
那多型應該跟繼承有關係對嗎??? 沒繼承就沒有多型問題存在我這樣說對嗎??
多型都是在指虛擬函式嗎??? 函式多載( 函式名稱相同參數有差異 )也能說是多型的一種嗎??
to aftcast 你車子舉例也不錯^^~~
謝謝
Stallion
版主


發表:52
回覆:1600
積分:1995
註冊:2004-09-15

發送簡訊給我
#5 引用回覆 回覆 發表時間:2006-12-31 09:15:32 IP:211.22.xxx.xxx 未訂閱
===================引 用 文 章===================
那就是說封裝是OO特性 , 跟繼承沒有直接關係是嗎??
是的。封裝的好處就是保護類別的重要資料,改善以往程式的缺點。
那多型應該跟繼承有關係對嗎??? 沒繼承就沒有多型問題存在我這樣說對嗎??
完全正確。
多型都是在指虛擬函式嗎??? 函式多載( 函式名稱相同參數有差異?)也能說是多型的一種嗎??
多型不是在指虛擬函式,多型指的是子類別繼承父類別後產生的關係型態,而虛擬函式則屬於類別,虛擬函式主要為父類別提供給子類別Overload或Overwrite,以相同的函式名稱,做不同的功能需求;函式的多載是獨樹一格的,跟類別的多型不同,看原文就知道意思了。多型(Polymorphism),多載(Overload)。

yshihyu
一般會員


發表:23
回覆:18
積分:8
註冊:2006-11-28

發送簡訊給我
#6 引用回覆 回覆 發表時間:2006-12-31 11:13:26 IP:59.104.xxx.xxx 訂閱
To Stallion 謝謝
想再請問有繼承關係一定就有所謂多型嗎 ?? 或是說怎麼才能算是真正達到多型 ??
aftcast 休旅車繼承車子特性 , 這樣就能說是多型嗎??
書上是以形狀類別舉例 ,它可以給各種形狀的類別的去繼承 , 三角形 , 方形 , 長方形 這樣算是多型
還有 is - a , has -a 搞不太懂之間差異
is -a 書上是說公用(public)繼承指繼承介面 , 基礎類別能做到的事情 , 衍生類別都可以辦到 是 is-a
has - a 是取得實作但無介面, 以好像取得實作的子物件 // 我這樣解釋不知道是否聽的懂我的意思@@
謝謝
aftcast
站務副站長


發表:81
回覆:1485
積分:1763
註冊:2002-11-21

發送簡訊給我
#7 引用回覆 回覆 發表時間:2006-12-31 15:27:56 IP:60.248.xxx.xxx 訂閱
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

發送簡訊給我
#8 引用回覆 回覆 發表時間:2006-12-31 16:38:11 IP:203.73.xxx.xxx 訂閱
(亂入開始)
我還是喜歡用車子來說

車輛假設可以被定義成顏色、油量、出力、輪數等「屬性」
而車子可以被發動、加油、移動、加速、停止等等「方法」
而機車可以被定義為是一個繼承自車輛類別,只有兩輪的車輛,
轎車則是一個繼承自車輛,有四輪的車輛
這就是多型,而繼承的類別則是「專化」並窄化上層類別的定義,如上例,機車就只能有兩輪,轎車只能有四輪
我們都知道有例外,所以我們在定義我們要使用的類別的時候必須要注意這些問題

而我們希望車子是「可以被駕駛的」,也就是它必須要符合「發動」、「移動」、「控制方向」
於是我們定義「駕駛」必須要有這些行為,這就是所謂的介面,
它不去管誰來用這個介面,總之這個介面只負責這些行為,要用這個介面的人必須要依照這個介面的定義去撰寫這些行為

而車子發動的方法大多數都是用鑰匙,但是某些車子會提供不同的發動方式,比如說按按鍵,或者是語音發動
那麼我們就可以讓這個類別有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

發送簡訊給我
#9 引用回覆 回覆 發表時間:2007-01-01 03:20:59 IP:59.104.xxx.xxx 訂閱

===================引 用 文 章===================
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()

我想知道pe->range(); 這樣是會不會讓編譯器產生錯誤,因為書上說這樣是不安全,
不過我感覺這樣就是有問題就如註解上說的Employee 不一定有 range() , 那這樣到是會產生錯誤嗎??
1 向上轉型在c  實作上都是安全的嗎??? 只是類別關係間如你所講的不完美現象
2 向下轉型是不是都存在不安全性 如果上面的pe->range(); 問題 , 是否有什麼解決的辦法避免 , 還是在處理向下轉型的時候在去注意?? 
3 最後想知道在虛擬函式也有向上或向下轉型存在問題嗎??  
謝謝
 
暗黑破壞神
版主


發表:9
回覆:2301
積分:1627
註冊:2004-10-04

發送簡訊給我
#10 引用回覆 回覆 發表時間:2007-01-01 09:02:31 IP:61.225.xxx.xxx 訂閱
嗯。看了這麼久。怎麼沒有人把”封裝””繼承””多型”實際拿出簡單的 code 的解說一下勒。
繞在中文字面上解說,很難讓初學者搞懂勒。
系統時間:2024-05-07 6:35:30
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!