1、派生類物件包含以下特徵:
1、派生類物件儲存了基類的資料成員(派生類繼承了基類的實現);
2、派生類物件可以使用基類的方法(派生類繼承了基類的實現);
2、繼承特性中需要另外新增什麼?
1、派生類需要自己的建構函式;
2、派生類可以根據需要新增額外的資料成員和成員函式;(派生類需要自定義的函式都用虛函式表示)
注意:派生類不能直接訪問基類的私有成員,而必須通過基類方法進行訪問。所以繼承類的建構函式不能直接設定繼承的成員,而必須通過基類的公有方法來訪問私有的基類成員。具體地說,派生類建構函式必須使用基類建構函式(可能不止乙個基類建構函式,所以需要指定使用哪個,可以用初始化器列表語法指明;若基類沒有顯示定義的複製建構函式,則呼叫預設的複製建構函式,而預設的複製建構函式裡面最好不要有new的指標)。建立派生類物件時,程式首先建立基類物件(可以這樣理解,繼承父類的遺產,實際上是連著父親的軀殼一起繼承,主要作用是初始化繼承的資料成員,派生類主要初始化新增的資料成員,分工合作),這意味著基類物件應當在程式進入派生類建構函式之前被建立。c++使用成員初始化列表來完成這項工作。如下:
derived::derived(type1 x,type2 y) : base(x,y)
其中,derived是派生類,base是基類,x和y是基類建構函式使用的變數。成員初始化列表只能用於建構函式(方法檔案中初始化列表)。
3、有關派生類建構函式的要點如下:
首先建立基類建構函式;
派生類建構函式應通過成員初始化列表將基類資訊傳遞給基類建構函式;
派生類建構函式應初始化派生類新增的資料成員;
4、派生類的使用
要使用派生類,程式必須能夠訪問基類宣告(即必須包含基類宣告在標頭檔案中)。
5、基類與派生類的特殊關係
派生類可以使用基類的非私有方法;
基類指標可以在不進行顯示型別轉換的情況下指向派生類物件;
基類引用可以在不進行顯示型別轉換的情況下引用派生類物件;如:
ratedplayer rplayer1(1140,"ab","cd",true);
tabletenniseplayer & rt = rplayer;
tabletenniseplayer * pt = &rplayer;
rt.name();//invoke name() with reference;
pt->name();//invoke name() with pointer;
然而基類指標或引用只能呼叫基類方法,不能呼叫派生類方法(單向呼叫);
不可以將基類物件和位址賦給派生類物件引用和指標。
引用相容性,只可以向上相容,即可以引用基類或指向基類的,也可以引用(實質也是指標)派生類或指向派生類。
向上強制轉換:將派生類引用或指標轉換為基類引用或指標被稱為向上強制轉換。這使公有繼承不需要進行強制轉換(is-a關係);另外向上轉換帶來安全操作,因為向上強制型別轉換的實質是派生類間接呼叫基類的方法,基類中的方法派生類也有,所以是安全的。(隱式向上強制型別轉換因此需要動態聯編,c++使用虛成員函式來滿足這種需求)。
向下強制轉換:將基類引用或指標轉換為派生類指標或引用稱為向下強制型別轉換。必須顯式轉換,這是因為向下強制轉換的實質是把基類(物件)強制向下轉化為派生類(物件),基類呼叫派生類的方法(不屬於基類)肯定會出現問題。
也可以將基類物件初始化為派生類物件,只不過是將基類物件巢狀在派生類物件當中;
也可以將派生類物件賦值給基類物件。賦的是派生類物件的基類部分。
6、is-a關係;公有繼承派生類和基類的關係;如banana is-a kind of(是一種) fruit;此關係通常不可逆轉;
多型公有繼承的兩種重要機制:
在派生類中重新定義基類的方法;
使用虛方法(在基類中將派生類會重新定義的的方法宣告為虛方法,在基類中被宣告為虛方法後,他在派生類中將自動成為虛方法;在基類宣告乙個虛析構函式也是慣例,;故虛方法對應虛析構函式,就像建構函式對應析構函式一樣);關鍵字virtual;
特註:如果基類中宣告了虛析構函式,則派生類物件中重定義了新的成員函式時,當此物件過期時,將先呼叫基類的析構函式,釋放基類的記憶體,再呼叫派生類物件的析構函式釋放新產生的記憶體。所以,在基類中需要宣告虛析構函式,即使它本身用不著虛析構函式,但是派生類需要。
如宣告 某一虛函式其格式為 :
virtual void view() const;
派生類方法可以呼叫公有的基類方法,但派生類方法定義時需加上作用域解析運算子,否則同名的(虛)方法會引起無限遞迴呼叫.
7、函式名聯編:將源**中的函式呼叫解釋為執行特定的函式**塊被稱為函式名聯編。(聯編,編譯器根據函式引數以及函式名來選擇呼叫函式的過程)
靜態聯編:在編譯過程中進行聯編被稱為靜態聯編;(效率更高)
動態聯編:使用哪乙個函式是不能在編譯時確定的(如虛成員函式),因為編譯器不知道使用者將選擇哪種物件。所以編譯器必須生成能夠在程式執行時選擇正確的虛方法的**,這被稱為動態聯編(隱式向上強制型別轉換需要動態聯編)。
靜態動態聯編比較:
靜態效率更高,因為固定,就像固定陣列分配好了大小一樣,在編譯時就已經確定了;而動態聯編在編譯時才確定使用哪個物件的方法,是不是用也不一定,若不使用就浪費效率;
而使用動態聯編需要使用虛函式,虛函式使用時會增大記憶體和執行速度方面的成本,包括:
每個物件都將增大,增大量為儲存位址的空間;
對於每個類,編譯器都將建立乙個虛函式的位址表(陣列);
對於每個函式,都需要執行一項額外的操作,即到表中查詢位址;
所以,各有優劣勢。
8、虛函式注意事項:派生類中重新定義基類中的方法並不是過載。無論引數列表是否相同,該操作將隱藏所有的同名基類方法。
經驗:如果重新定義繼承的方法,應確保與原來的原型完全相同,但如果返回型別是指標或基類引用,則可以修改為指向派生類的指標或引用(返回型別協變)。
如果基類方法宣告被過載(同名函式特徵標不一致)了,則應在派生類中重新定義所有的基類版本。
9、protected成員:與private相似,在類外只能用公有成員函式訪問,這二者區別只有在基類的派生類中才能體現出來;派生類成員可以直接訪問基類的保護成員,但不能直接訪問基類的私有成員。
訪問許可權 public > protected >private
最好對類資料成員採用私有訪問控制,不要用保護訪問控制;同時能夠通過基類方法使派生類能夠訪問基本資料。
然而,對於成員函式來說,保護訪問控制很有用,他讓派生類能夠訪問公眾不能使用的函式。
10、純虛函式:c++通過使用純虛函式提供未實現的函式;純虛函式宣告的結尾處為 = 0;
如vrtual double area() const = 0;
當類宣告中包含純虛函式時,則不能建立該類的物件。這裡的理念是,包含純虛函式的類只作用於基類。要成為真正的抽象類abc(abstract base class),必須至少包含乙個純虛函式。
第十三章 類
1.類簡單地說是乙個性的資料型別。類當中有資料成員,和成員函式。類的基本思想就是體現出資料的抽象和封裝。2.這裡只需要說明乙個問題即可 就是類成員函式的const型別 class screen public const int get const int i const int j const 這裡...
第十三章 併發
13.1 動機 13.2 基本執行緒 如果必須要控制現成的執行順序,最好是根本不用執行緒,而是自己編寫特定順序彼此控制的協作子程式。繼承thread類或者實現runnable介面。內部類實現。13.3 共享受限資源 1 如果要對類中的某個方法進行同步控制,最好同步所有方法。如果忽略了其中乙個,通常很...
第十三章 事件
1 事件的作用 事件是對委託的封裝,如同屬性對字段的封裝。封裝後可以在委託上實現更複雜的邏輯。1.1 封裝訂閱 委託允許使用 對其進行賦值,但向乙個委託例項賦值多個委託時,使用 會造成覆蓋之前的委託。事件只支援 或 對事件進行賦值 1.2 封裝發布 委託可以在其他類進行訪問,而事件可以確保只有包容類...