tags: 大一程設-下 東華大學 東華大學資管系 基本程式概念 資管經驗分享

Inheritance 繼承

前言

繼承是物件導向的重要特性之一,可以讓我們避免撰寫不必要的程式,在往下閱讀之前,請務必先閱讀以下的參考資料。

C++ 其實有多重繼承,但他其實是有點糟糕的設計方式,我們不要學他。
等你們以後去學 JAVA 或其他語言會學到 super,學 super 比較重要。
[ C++ 沒有 super ]
Orange

語法說明

相信你已經看完上面的參考資料摟!

而且有理解衍生類別基礎類別的關係,這兩個名詞我們也常用一種代稱去形容他,衍生類別 = 子類別,基礎類別 = 父類別。子類別會繼承父類別的基本屬性與方法,而子類別亦可獨立出有別於父類別自己擁有的屬性與方法。

基本概念都有之後,來把語法記熟吧!

以下例子為了演示方便,屬性、方法全都放 public,但理論上屬性應該要放 private,用 getter & setter 去存取他喔,封裝的概念不要忘記。
Orange

class Animal{ public: string type; void walk(){ cout << type << " walk" << endl;} void jump(){ cout << type << " jump" << endl;} }; class Dog : public Animal{ public: void bark(){ cout << type << " bark" << endl;} }; class Bird : public Animal{ public: void fly(){ cout << type << " fly" << endl;} }; int main() { Dog d1; d1.type = "dog"; d1.walk(); d1.jump(); d1.bark(); Bird b1; b1.type = "bird"; b1.walk(); b1.jump(); b1.fly(); return 0; }

因為 Dog 跟 Bird 都公開繼承 Animal,所以子類別可以存取父類別的所有 public 屬性。

而繼承要使用的是 : 運算子,在要繼承別人的類別後加上 : 存取權限 類別名稱,這是固定語法。

公開繼承的概念就是 is-a 的概念,什麼意思呢? 看了上面繼承的例子,你會發現 Dog 跟 Bird 都可以使用父類別 (Animal) 的 public 屬性與方法,所以我們可以說 :

Bird is an Animal.
Dog is an Animal.

而這邊一直提到的公開繼承就是在 : 後加上的 public,寫 public、private、protected,其效果會有所不同。

這邊我們都先知道 public 公開繼承就可以了,當你公開繼承某個類別的時候,被繼承的類別的 public 屬性或方法都可以在子類別內被呼叫使用,而 private 屬性與方法則無法在子類別內直接呼叫使用。

上面說明的 public 與 private,有的是在表達繼承,有的是在表達類別內屬性與方法的權限,要會分哦。
Orange

[補充 - 自行閱讀]公開繼承? 私有繼承? 保護繼承?

上面說的內容與範例你了解了的話,你應該知道在 : 後寫不同的存取修飾子可能會有不同的事情產生,以下是參考資料,有問題歡迎來問我~

這邊提的是繼承的模式哦! 不是類別內屬性與方法的存取權限。
在往下閱讀之前,請務必先閱讀以下的參考資料。

簡單的說,採用什麼類型的繼承,其繼承下來的屬性與方法就變成何種類型。
Orange

public 公開繼承就是上面的程式碼範例不再說明。

若為 protected 保護繼承,假設 Dog protected 繼承 Animal,程式碼像這樣。

class Animal{ public: string type; void walk(){ cout << type << " walk" << endl;} void jump(){ cout << type << " jump" << endl;} }; class Dog : protected Animal{ public: void bark(){ cout << type << " bark" << endl;} }; int main(){ Dog d1; d1.type = "dog"; d1.walk(); d1.jump(); }

上面這樣的程式碼是錯的,因為保護繼承,Dog 繼承 Animal 之後對於 Dog 而言 type、jump、walk 全都變成 protected member,所以 Animal 的屬性與方法對於 Dog 而言,只有 Dog 類別本身看的到,實體化後的物件是無法存取的。

protected member 的參考資料在最下面
Orange

所以你必須在 Dog 類別內實作 getter & setter 才能存取 Animal 的 public 屬性與方法。像這樣。

class Animal{ public: string type; void walk(){ cout << type << " walk" << endl;} void jump(){ cout << type << " jump" << endl;} }; class Dog : protected Animal{ public: void bark(){ cout << type << " bark" << endl;} void set_type(string t){ type = t; } void walkAndJump(){ walk(); jump(); } }; int main(){ Dog d1; d1.set_type("dog"); d1.walkAndJump(); d1.bark(); }

再延伸一點,假設今天有一隻可以從嘴巴噴火的狗狗,而且還會飛,那該怎麼辦,當然可以在現有的 Dog 內做改動,但如果又有一隻會招喚閃電,而且可以砍樹的狗狗,難道又要在 Dog 內增加嗎?

這樣其實沒甚麼效率,所以會再新增類別來繼承 Dog。但是因為繼承,所以 FireDog 仍舊保有 Dog 的屬性與方法。

FireDog is a Dog!
class Animal{ public: string type; void walk(){ cout << type << " walk" << endl;} void jump(){ cout << type << " jump" << endl;} }; class Dog : protected Animal{ public: void bark(){ cout << type << " bark" << endl;} void set_type(string t){ type = t; } void walkAndJump(){ walk(); jump(); } }; class FireDog : public Dog{ public: void fire(){cout << type << " fire" << endl;} void fly(){cout << type << " fly" << endl;} };

請問對於 FireDog 而言,如果做 protected 繼承,該怎麼改寫程式呢?

更多變形留給大家自行思考,有問題歡迎來問~

[補充 - 自行閱讀] protected member

這邊提的是針對屬性與方法的存取權限,與上面完全不同,拜託請別搞混,分清楚。