物件導向程式設計與泛型程式設計

2021-07-05 11:16:11 字數 3990 閱讀 7325

第15章 物件導向程式設計

物件導向程式設計基於資料抽象、繼承、動態繫結三個基本概念。在c++中,用類進行資料抽象,用類派生從乙個類繼承另乙個類:派生類繼承基類的成員。動態繫結使編譯器能夠在執行時決定是使用基類中定義的函式還是派生類中定義的函式。

(物件導向的三大特徵:封裝、繼承、多型)

-15.1 物件導向程式設計:概述

物件導向程式設計的關鍵思想是多型性,在c++中,多型性僅用於通過繼承而相關聯的型別的引用或指標。

--1. 繼承

非虛函式:基類定義,派生類繼承

虛函式:基類先定義,派生類重新定義

純虛函式:基類不定義,每個派生類必須定義

--2. 動態繫結

通過基類的引用(或指標)呼叫虛函式時,發生動態繫結。引用(或指標)既可以指向基類物件也可以指向派生類物件。用引用(或指標)呼叫的虛函式在執行時確定。

-15.2 定義基類和派生類

--15.2.1 定義基類

繼承層次的根類一般都要定義虛析構函式。

---1. 基類成員函式

非虛函式的呼叫在編譯時確定,虛函式的呼叫在執行時確定。

除建構函式外,任意非static成員函式都可以是虛函式。

---2. 訪問控制和繼承

public:都可以訪問

protected:this、友元、派生類可以訪問

private:this、友元可以訪問,派生類不能訪問

--15.2.2 protected成員

派生類只能通過派生類物件訪問其基類的protected成員,不能通過基類物件訪問其基類的protected成員。

例如,void bulk_item::fun(item_base& base, bulk_item& derive);可以通過derive訪問item_base類的protected成員,但不能通過base訪問item_base類的protected成員。

--15.2.3 派生類

class classname: access-label base-class

access-label決定了對繼承成員的訪問許可權。如果想要繼承基類的介面,則應該進行public派生。

---1. 定義派生類

---2. 派生類和虛函式

如果派生類沒有重定義某個虛函式,則使用基類中定義的版本。

派生型別必須對想要重定義的每個繼承成員進行宣告,且宣告必須與基類中的定義方式完全匹配,但有乙個例外:返回對基型別的引用(或指標)的虛函式。派生類中的虛函式可以返回基類函式所返回型別的派生類的引用(或指標)。

----3. 派生類物件包含基類物件作為子物件

派生類物件:派生類本身定義的(非static)成員 + 基類(非static)成員。

---4. 派生類中的函式可以使用基類的成員

類可以訪問其基類的public和protected成員。

---5. 用作基類的類必須是已定義的

---6. 用派生類作基類

最底層的派生類物件包含其每個直接基類和間接基類的子物件。

---7. 派生類的宣告

如果需要宣告但並不實現乙個派生類,則宣告包含類名但不包含派生類列表。

--15.2.4 virtual與其他成員函式

動態繫結發生的條件:

①只有指定為虛函式的成員函式才能進行動態繫結

②必須通過基類型別的引用或指標進行函式呼叫

---1. 從派生類到基類的轉換

double print_total(const item_base&, size_t);
基類型別的引用或指標可以引用基類型別物件,也可以引用派生類型別物件。無論實際物件具有哪種型別,編譯器都將它當作基類型別物件。

---2. 可以在執行時確定virtual函式的呼叫

引用和指標的靜態型別(基類)與動態型別(基類或派生類)可以不同--多型性。

物件是非多型的--物件型別已知且不變,物件的動態型別總是與靜態型別相同。

只有通過引用或指標呼叫,虛函式才在執行時確定。

---3. 在編譯時確定非virtual呼叫

非虛函式總是在編譯時根據呼叫該函式的物件、引用或指標的型別而確定。

---4. 覆蓋虛函式機制

目的:為了派生類虛函式呼叫基類中的版本。

注意:派生類虛函式呼叫基類版本時,必須顯式使用作用域操作符。如果派生類函式忽略了這樣做,則函式呼叫會在執行時確定並且將是乙個自身呼叫,從而導致無窮遞迴。

---5. 虛函式和預設實參

虛函式也可以有預設實參,在函式呼叫時:

①給定實參:該值在編譯時確定;

②省略實參:由呼叫該函式的型別確定,與物件的動態型別無關。通過基類的引用或指標呼叫虛函式時,預設實參為在基類虛函式宣告中指定的值;如果通過派生類的指標活引用呼叫虛函式,則預設實參是在派生類的版本中宣告的值。

--15.2.5 公用/私有和受保護的繼承

派生訪問標號將控制派生類的使用者對從base繼承而來的成員的訪問。

---1. 介面繼承和實現繼承

public繼承:介面繼承

protected或private繼承:實現繼承

---2. 去除個別成員

size在base中為public,但在derived中為private。為了使size在derived中成為public,可以在derived的public部分增加乙個using宣告。

class derived:private base

---3. 預設繼承保護級別

使用class保留字定義的派生類預設具有private繼承,而用struct保留字定義的派生類預設具有public繼承。

--15.2.6 友元關係與繼承

友元關係不能繼承,基類的友元對派生類的成員沒有特殊的訪問許可權。

--15.2.7 繼承與靜態成員

無論從基類派生出多少個派生類,每個static成員只有乙個例項。

假定可以訪問成員,則既可以通過基類也可以通過派生類訪問static成員。

-15.3 轉換與繼承

可以將派生類物件的引用轉換為基類子物件的引用,對指標也類似。

沒有從派生型別物件到基類型別物件的直接轉換。

--15.3.1 派生類到基類的轉換

----1. 引用轉換不同於轉換物件

將派生類物件傳給希望接受基類引用的函式:引用直接繫結到該物件

將派生類物件傳給希望接受基類物件(而不是引用)的函式:派生類物件的基類部分被複製到形參

----2. 用派生類物件對基類物件進行初始化或賦值

①基類可能顯式定義了將派生類物件複製或賦值給基類物件的含義(不常見)

②基類一般(顯式或隱式)定義自己的複製建構函式和賦值操作符,形參是基類型別的const引用(常見)

----3. 派生類到基類轉換的可訪問性

public繼承:可訪問

private或protected繼承:不能將派生類物件轉換為基類物件

---15.3.2 基類到派生類的轉換

基類到派生類的自動轉換是不存在的。如果知道從基類到派生類的轉換是安全的,可以使用static_cast強制編譯器進行轉換,或者用dynamic_cast申請在執行時進行檢查。

-15.4 建構函式和複製控制

建構函式和複製控制成員不能繼承,每個類定義自己的建構函式和複製控制成員。

--15.4.1 基類建構函式和複製控制

某些類需要只希望派生類使用的特殊建構函式,應定義為protected。

--15.4.2 派生類建構函式

---1. 合成的派生類預設建構函式

呼叫基類的預設建構函式初始化物件的基類部分。

---2. 定義預設建構函式

---3. 向基類建構函式傳遞實參

派生類建構函式通過將基類包含在建構函式初始化列表中來間接初始化繼承成員。

---4. 在派生類建構函式中使用預設實參

---5. 只能初始化直接基類

乙個類只能初始化自己的直接基類,原因是每個類都定義了自己介面。

物件導向程式設計VS泛型程式設計

物件導向程式設計vs泛型程式設計 1 物件導向 oop是對data operation的封裝,是對同類事物的抽象,跟結構化程式設計相比它更接近自然語言。繼承使得oo具有了更強的表達能力,進一步地接近了自然語言的屬性。而多型則是oo的最為巧妙和強大的地方,它催生了一系列的設計模式,而設計模式的應用體現...

c 物件導向程式設計 泛型

泛型類是引用型別,是堆物件。優點 不會強行堆值型別進行裝箱和拆箱,或對引用型別進行向下強制型別轉換,所以效能能得到了提高。list可儲存任意指定型別的集合 優點 與arraylist型別的集合相比,arraylist 在新增string型別時,string型別會隱式強制轉換為object型別。同樣,...

模板與泛型程式設計

模板是泛型變成的基礎。泛型程式設計 編譯與型別無關的 是一種復用的方式,模板分為模板函式和模板類。模板函式是乙個通用的函式模板,而不是為每一種型別定義乙個新函式,乙個函式模板就像乙個公式,針對不同型別函式生成不同的函式版本。關鍵字 template 以 template 開始,後面跟乙個模板引數列表...