條款32:確定你的pubilc繼承塑模出is-a關係
Make sure public inheritance models “is-a”
– C++進行(OOP)物件導向編程,最重要的一個規則是:public inheritance (公開繼承)意味“is - a”(是一種)關係。
– 如果你令class D(“derived”)以public形式繼承class B(“Base”),你便是告訴編譯器: 每一個類型為D的對象同時也是一個類型為B的對象,反之不成立。
– “pubilc繼承”意味is-a。適用於Base classes身上的每一件事情一定也是用於Derived classes 身上,因為每一個Derived class對象也都是一個Base Class對象。
條款33:避免遮掩繼承而來的名稱
Avoid hiding inherited names.
– Derived classes內的名稱會隱藏Base classes內的名稱。
– 為了能讓被隱藏的名稱可以使用,可用using聲明式或(轉交函數)。
條款34:區分介面繼承和實現繼承
Differentiate between inheritance of interface and inheritance ofimplementation
– Pure virtual函數有兩個最突出的特性:它們必須被任何“繼承它們”的具象class重新聲明,而且它們在抽象class(基類)中通常沒有定義。
• 聲明一個purevirtual函數的目的是為了derived classes只繼承函數介面。
• 聲明一個impurevirtual函數的目的,是讓derived classes繼承該函數的介面和預設實現。
• 聲明non-virtual函數的目的是為了令derivedclasses繼承函數的介面及一份強制性實現。
– 介面繼承和實現繼承不同。在pubilc繼承下,derivedclasses總是繼承Base class 的介面。
– Pure virtual函數只具體指定介面繼承。
– Impure virtual 函數具體指定介面繼承及預設實現繼承。
– Non-virtual函數具體指定介面繼承以及強制性實現繼承。
條款35:考慮virtual函數以外的其他選擇 Consider alternative to virtual functions.
– 使用non-virtualinterface(NVI)手法,那是Template Method設計模式的一種特殊形式。它以public non-virtual成員函數包裹較低訪問性(private 或protected)的virtual函數。
將virtual函數替換為“函數指標成員變數”。將功能從成員函數移到class外部函數,帶來一個缺點是,非成員函數無法訪問class的non-public成員
條款36:絕不重新定義繼承而來的non-virtual函數
Never redefine an inherited non-virtual function.
– 絕對不要重新定義繼承而來的non-virtual函數。
條款37:絕不重新定義繼承而來的預設參數值
– Nerver redefine a function’s inherited default prameter value.
– 絕對不要重新定義一個繼承而來的預設參數值,因為預設參數值都是靜態繫結,而virtual函數-----你唯一應該複寫的東西-------卻是動態綁定。
條款38:通過複合塑模出has-a或“根據某物實現出” Model “has-a” or “is-implemented-in-terms-of”through composition.
– 複合(composition)是類型之間的一種關係,當某種類型的對象內含它種類型的對象,便是這種關係。
– 複合(composition)的意義和public繼承完全不同。
– 在應用域(applicationdomain),複合意味has-a(有一個)。在實現域(implementation domain),複合意味is-implemented-in-terms-of(根據某物實現出)。
條款39:明智而審慎地使用private繼承 Use private inheritance judiciously.
– 如果classes之間的繼承關係是private,編譯器不會自動將一個derivedclass對象轉換為一個Base class對象。
– Private base class繼承而來的所有成員,在derived class中都會變成private屬性。
c++裁定凡是獨立(非附屬)對象都必須有非零大小。勒令默默安插一個char到Null 物件內。
EBO(空白基類最佳化):
class Empty();
class HoldsAnInt : private Empty
{
private:
int x;
}
sizeof(HoldsAnInt) == sizeof(int);
條款40:明智而審慎的使用多重繼承 Use multiple inheritance judiciously
– 多重繼承比單一繼承複雜。它可能導致新的歧義性,以及對virtual繼承的需要。
– Virtual繼承會增加大小、速度、初始化(及賦值)複雜度等等成本。
– 多重繼承的確有正當用途。其中一個情節涉及“public繼承某個Interface class”和“private繼承某個協助實現的class”的兩相結合