C++88個注意點子之71~88

71. 操作符重載:

(1)不能通過連接其他符號來創建任何新操作符,如**(冪)非法

(2)不內置類型定義額外的新操作符(如不能爲數組定義+)

(3)重載操作符必須具有至少一個類類型或枚舉類型的操作數

(4)優先級和結合性是固定的,重載操作符使用默認實參非法

(5)操作符定義爲非成員函數時,通常必須將它設置爲所操作類的友元

(6)賦值操作符,取地址操作符,逗號操作符對類類型操作數有默認含義

(7)關聯容器鍵類型應定義<操作符,順序容器中,爲了算法可用,應定義==,<操作符

(8)選擇成員or 非成員實現:=,[ ], (), ->必須定義爲成員複合賦值也應定義爲成員,++, -- , *等一般爲類成員,對稱的操作符,如算術,相等,關係,位操作符,最好定義爲非成員函數。


72.函數對象,定義了operator()成員函數

可用參考標準庫函數對象(類模板),在C++ Prime 第452頁


73. 類類型可轉換爲其他類型,需要定義operator 類名() const

類類型轉換之後不能再跟另一個類類型轉換。標準轉換可放在類類型轉換之前。


74. 多態

(1) 動態多態: 類繼承和虛函數機制(動態綁定實現)

(2) 靜態多態: 1. 非參數化多態(函數重載,運算符重載) 2. 參數化多態:泛型編程(類型作爲參數)


75. 動態綁定:通過基類的引用(或指針)調用虛函數,發生動態綁定。引用(或指針)可指向基類也可指向派生類對象,用引用(或指針)調用的虛函數在運行時確定。


76. 一般基類需要定義虛析構函數,static成員函數不可爲虛函數,virtual只在類內部的成員函數聲明中出現,不能在類定義體外函數定義上出現。


77. 基類中的public成員可被派生類訪問,但private成員不能被訪問,protected成員可被派生類訪問,但不能被其他用戶訪問。

基類只對外部提供public,而派生類則可以訪問基類的protected, 但在派生類定義函數內部不能訪問基類對象的protected。


78. 引用和指針的靜態類型與動態類型可以不同,這是C++用以支持多態性的基石。 

對象的類型已知且不變,對象是非多態的。對象的動態類型總是與靜態類型相同,這與引用和指針相反。


79. (1) 編譯時確定非virtual調用

(2) 覆蓋虛函數機制


80. 通過基類的引用或指針調用虛函數時,默認實參爲在基類虛函數中聲明的值,若通過派生類的指針或引用調用虛函數,則默認實參是在派生類的版本中聲明的值。


81. 公用,私有和受保護的繼承

(1) 公用繼承(public基類):基public -> 派public; 基protected -> 派protected

(2) 受保護繼承(protected基類):基public, protected -> 派protected

(3) 私有繼承(private基類):基所有 -> 派private


82. 默認繼承保護級別

class Base;

struct D1: Base -> struct D1: public Base

class D2: Base -> class D2: private Base


83. 友元關係與繼承:友元關係並不能繼承。基類的友元對派生類成員沒有特殊訪問權限。


84. 派生類-> 基類:

(1) 引用轉換不同於轉換對象

(2) 用派生類對象對基類對象進行初始化或賦值

(3) 派生類到基類轉換的可訪問性


85. 派生類構造函數:先調用基類的默認構造函數,然後再執行派生類的構造函數。

(1) 向基類構造函數傳遞實參:

Bulk_item(const std::string &book, ...): Item_base(book, sales_price), min_qty(), discard() {}

(2) 派生類只能使用直接基類構造函數初始化,初始化直接基類


86. 複製構造函數,賦值構造函數,析構函數一般都是先基類,再派生類的順序進行。

(1) 對於複製構造函數,若不定義,則使用合成複製構造函數(先基類複製,再派生類部分),若派生類定義了自己的複製構造函數,該複製構造函數一般應顯式使用基類複製初始化自己基類部分,不然,則運行Base默認構造函數初始化對象(會出問題的)

(2) 賦值同複製,若派生類顯式定義了自己的賦值操作符,則必須對基類部分進行顯式賦值。Base::operator=(rhs);

(3) 析構函數不一樣,只負責撤銷自己的部分,從底往上逆序撤銷基類。


87. 基類的虛析構函數總是需要的,防止指針指向派生類。複製構造函數,構造函數,賦值操作符一定不能用虛函數。


88. 派生類作用域中嵌套着基類作用域,若派生類中成員名與基類相同,則屏蔽基類中成員,若在派生類中還想用基類成員,則Base::mem; 在派生類中定義與基類函數名一樣的函數,則屏蔽基類中的,是屏蔽,不是重載,不管形參等怎樣不同都屏蔽。

局部作用域中聲明的函數不會重載全局作用域中函數。

基類作用域 {

     派生類作用域

}


89. 派生類中的重載函數,要麼重定義函數,屏蔽基類,要麼不定義,用基類重載函數。若想打破,則用using Base::函數名; 不用形參表。接着定義自己的函數。


90. 派生類中定義了與基類虛函數同名函數,但形參不一樣,則屏蔽,若又定義了相同形參函數,則依次管用。


91. 純虛函數,聲明如下:virtual 返回類型 函數名(參數) = 0;

純虛函數一定沒有定義,純虛函數用來規範派生類的行爲,即接口。包含純虛函數的類是抽象類,不能實例化,但可以定義該類類型的指針或引用,同時,該類的派生類中必須實現虛函數具體行爲,不然報錯。


92. 如果虛函數的基類實例返回類類型的引用或指針,則該虛函數的派生類實例可以返回基類實例返回的類型的派生類(或者類類型的指針或引用)。


93. 句柄類,管理類類型指針,特別對於基類和派生類問題有效。句柄類(智能指針)是存儲指向動態分配(堆)對象指針的類。


最後加了幾個注意點微笑,寫完感覺C++的語法真的很複雜,比java複雜好多。個人感覺java取消了操作符重載是明智的,而且取消了多繼承,改用接口來規範更是一大進步。下面一段時間希望來將java的多個注意點整理好搬上來,在java篇的注意點中整好與c++的語法特性相比,讓大家感受一下java的編程優勢。(我並不是一個java控,本人最喜歡的語言是python)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章