C++的另一個目標是促進代碼重用。公有繼承是實現這種目標的機制之一,但并不是唯一的機制。還可以使用這樣的類成員:本身是另一個類的對象,這種方法稱為包含、組合或層次化。另一種方法是使用私有繼承或保護繼承。類模板是另一種重用代碼的方法,類模板使我們能夠使用通用術語定義類,然后使用模板來創建針對特定類型定義的特殊類。
通過組合(包含)即創建一個包含其他類對象的類,用于建立has-a關系。使用公有繼承時,類可以繼承接口,可能還有實現(基類的純虛函數提供接口,但不提供實現),獲得接口是is-a關系的組成部分。而使用組合,類可以獲得實現,但不能獲得接口,不繼承接口是has-a關系的組成部分。 C++包含讓程序員能夠限制程序結構的特性——使用explicit防止單參數構造函數的隱式轉換,使用const限制方法修改數據等等。 當初始化列表包含多個項目時,這些項目被初始化的順序為它們被聲明的順序,而不是它們在初始化列表中的順序。 被包含類對象的接口不是公有的,但可以在類方法中使用它。
使用私有繼承,基類的公有成員和保護成員都將稱為派生類的私有成員,這意味著基類方法將不會稱為派生對象公有接口的一部分,但可以在派生類的成員函數中使用它們,基類的公有方法稱為派生類的私有方法,派生類不繼承基類的接口。使用私有繼承,類將繼承實現。 要使用私有繼承,需要使用關鍵字PRivate而不是public來定義類(private是默認值,省略訪問限定符也將導致私有繼承)。 使用私有繼承時,只能在派生類的方法中使用基類的方法,使用包含時將使用對象名來調用方法,而使用私有繼承時將使用類名和作用域解析運算符來調用方法。
使用多個基類的繼承被稱為多重繼承(MI)。C++多重繼承中引進了一種新技術——虛基類。虛基類使得從多個類派生出的對象只繼承一個基類對象。如果類有間接虛基類,則除非只需使用該虛基類的默認構造函數,否則必須顯式的調用該虛基類的某個構造函數。 多重繼承可能導致函數調用的二義性,可以使用作用域解析運算符來確定使用的方法,更好的辦法是重新定義該函數。還有一種辦法是使用模塊化方式。 如果類從不同的類繼承了兩個或更多的同名成員(數據或方法),則使用該成員名時,如果沒有用類名進行限定,將導致二義性,如果某個名稱優先于其他所有名稱,則使用它時,即便不使用限定符,也不會導致二義性,派生類中的名稱優先于直接或間接祖先類中的相同名稱。
繼承和包含并不總是能滿足重用代碼的需要,C++的類模板為生成通用的類聲明提供了一種更好的方法,模板提供參數化類型,即能夠將類型名作為參數傳遞給接收方來建立類或函數。
模板類以下面這樣的代碼開頭:
template <class Type>關鍵字template告訴編譯器,將要定義一個模板,尖括號中的內容相當于函數的參數列表,可以把關鍵字class看做是變量的類型名,該變量接受類型作為其值。class并不意味著Type必須是一個類,而只是表明Type是一個通用的類型說明符,在使用模板時,將使用實際的類型替換它,較新的C++實現允許使用關鍵字typename代替class。 模板不是類和成員函數定義,它們是C++編譯器指令,說明如何生成類和成員函數定義,模板的具體實現被稱為實例化或具體化。由于模板不是函數,它們不能單獨編譯,模板必須與特定的模板實例化請求一起使用。
僅在程序中包含模板并不能生成模板類,而必須請求實例化,為此,需要聲明一個類型為模板類的對象,方法是使用所需的具體類型替換泛型名。 指定特殊的類型而不是用作泛型名稱為非類型或表達式參數,表達式參數可以使整形、枚舉、引用或指針,模板代碼不能修改參數的值,也不能使用參數的地址,實例化模板時,用作表達式參數的值必須是常量表達式。
可以將用于常規類的技術用于模板類,模板類可用作基類,也可用作組件類,還可用作其他模板的類型參數,模板的多功能性有: - 遞歸使用模板,在模板語法中,維的順序與等價的二維數組相反。 - 模板可以包含多個類型參數。 - 可以為模板類型參數提供默認值。
類模板有隱式實例化、顯式實例化和顯式具體化,它們統稱為具體化。模板以泛型的方式描述類,具體化是使用具體的類型生成類聲明。 - 隱式實例化 一般使用的都是隱式實例化:聲明一個或多個對象,指出所需的類型,而編譯器使用通用模板提供的處方生成具體的類定義。 - 顯式實例化 當使用關鍵字template并指出所需類型來聲明類時,編譯器將生成類聲明的顯式實例化,聲明必須位于模板定義所在的名稱空間中。 - 顯式具體化 顯式具體化是特定類型(用于替換模板中的泛型)的定義。
新聞熱點
疑難解答
圖片精選