C++ 進階 教學 : 物件導向的進階觀念 - 封裝與繼承
C++ 進階 教學 : 物件導向的進階觀念 - 封裝與繼承
好的頻道需要你的支持,謝謝你使用Youtube影片的超級感謝功能給我們鼓勵。
好的頻道需要你的支持,謝謝你使用Youtube影片的超級感謝功能給我們鼓勵。
封裝
物件導向中用來實作資訊隱藏的機制,確保物件的安全。其作法為:隱藏不想讓外界碰觸的成員,只公開接受外界存取的成員。
一般而言,類別開發者為了物件的安全,會把資料成員全部隱藏起來,只公開存取或運算資料成員的函式成員。讓物件資料的修改,完全由函式成員掌控其值的變化,避免物件產生預期外的值。
成員存取的控制以存取修飾詞宣告的段落為單位。在宣告某一個存取修飾詞之後,另一個存取修飾詞出現之前為一個段落。若都沒有宣告,預設為 private 。- 存取修飾詞:
- private
- protected
- public
只允許本類別中的其他成員存取。
允許本類別的子類別存取。
允許所有類別存取。(用範例解釋存取)
從開始學物件導向起,一直向同學強調要有開發者與使用者的觀念。存取限制,是開發者用來限制使用者的存取權限。
當你在開發一個類別的時候(假設為類別A),你是類別A的開發者。在類別A中你有用到(存取)另一個類別的時候(假設為類別B),你是類別B的使用者。也就是說,在寫程式的時候,你大部份是身兼開發者與使用者的角色,所以容易混淆。
類別使用者使用類別的方式有二種:物件與繼承。
我們在開發的類別中用到 string 類別的時候,我們就是 string 類別的使用者。而我們是怎麼使用 string 類別呢?我們是建了 string 的物件,然後用物件儲存資料,再呼叫成員函式運算資料。這就是以物件方式使用類別,所以只能存取 public 成員。也就是說物件只能存類別中宣告為 public 的成員。
相對的,當你是類別開發者時。只有要讓物件可以存取的成員,才宣告為 public 。
本章只討論物件導向中比較常用(通用)的存取機制。關於C語言專有的 friend 本章不討論。
繼承
物件導向中用來避免程式碼重複撰寫與減低維護困難度的機制。子類別可以繼承父類別中的所有成員。也就是說,把多個類別都會用到的成員,寫在父類別中,子類別只要繼承父類別,不必再寫,就可以擁有那群成員。不但避免了程式寫的重複撰寫,也減少了日後維護的困難度。因為若有程式碼要修改,只需要修改一個類別。
當我們寫一個新類別,指定繼承某一個或多個己存在的類別時,就是在使用那一個或多個己存在的類別。新類別稱之為衍生類別 (Derived class) 或子類別 (Child class),己存在的類別稱之為基礎類別 (Base class) 或父類別 (Parent class)。子類別繼承父類別中的所有成員。但繼承了不代表可以存取,子類別不能存取父類別中宣告為 private 的成員,只能存取宣告為 protected 或 public 的成員。
當你是類別開發者時,不接受子類別與物件存取的,宣告為 private。不接受物件存取,但接受子類別存取的,宣告為 protected。接受物件存取的才宣告為 public。
繼承運算符號
:
繼承是為了在父類別的基礎之上,做進一步的開發。所以繼承不是重點,重點是繼承後的子類別可以做什麼?
子類別中可以:
- 新增子類別的成員
- 隱藏父類別的成員
- 若子類別中宣告與父類別中名稱相同的資料成員,子類別中的函式存取的是子類別中的資料成員。但父類別中的函式存取的是父類別中的資料成員。
- 若子類別中宣告與父類別名稱相同但參數列不同的函式,不是 Overloading,一樣是遮蔽了父類別的成員函式。
在子類別中可以新增父類別中沒有宣告的成員。
在子類別中可以宣告父類中己宣告過的成員,新宣告的成員會遮蔽父類別中相同名稱的成員。
建構函式
- 物件建立時,環境會在配置記憶體之後呼叫類別中定義的建構函式。類別開發者會在建構函式中撰寫物件初始化的程式碼,一般是指定資料成員的初值。建構函式的名稱必須與類別名稱一樣,可以有參數列,但不可以有返回型別。參數列可以宣告參數預設值。
- 預設的建構函式
- Overloading 建構函式
- this
每一個成員函式中都有一個隱含的指標 this。this可以指向呼叫此函式的物件,用來取存物件成員。
主要用途有二:- 在專業編輯環境中快速找到要存取的成員
- 解決成員變數與參數名稱重複的問題。
- 子類別的建構函式指定呼叫父類別的建構函式
建立物件時,若建立物件的敍述中沒有指定建構函式。環境預設會呼叫沒有參數的建構函式。所以沒有參數的建構函式就是預設的建構函式。
類別中若沒有撰寫建構方法,編譯器會自動產生沒有參數的建構方法。但是,自動產生的建構方法並不會自動指派資料成員的初值,所以建構出來的物件是不安全的。而且,若類別中有撰寫任何建構方法,編譯器就不會自動產生沒有參數的建構方法。
類別中除了沒有參數的建構函式,也可以視需求,Overloading 多個建構函式。
若父類別沒有預設的建構函式或 Overloading 多個建構函式,子類別的建構函式可以指定呼叫。
繼承存取限制
- 子類別在宣告繼承父類別的時候,可以用存取修飾詞限制父類別的成員在子類別中的新存取層級。
- private 在子類別中繼承自父類別的 private 成員等級不變,其餘等級成員一律改為 private。
- protected
- public
在子類別中繼承自父類別的 private 與 protected 的成員不變,public 成員改為 protected。
在子類別中繼承自父類別的所有成員等級均不變。
如下表格:
private | protected | public | |
private | private | private | private |
protected | private | protected | protected |
public | private | protected | public |
多重繼承
- 多重繼承是指子類別可以繼承多個父類別。宣告繼承時各個父類別名稱用 ',' 隔開,指定呼叫父類別的建構函式時,各個父類別的建構函式也是用 ',' 隔開。