單一繼承
在 「 單一繼承中,"一般形式的繼承,類別會有一個基底類別。 請考慮下圖所示的關係。
簡單的單一繼承圖形
請注意 [g/通用的進度,以特定圖形中。 在大部分的類別階層架構的設計中找到的另一個常見屬性被衍生的類別具有"的"的基底類別的關聯性。 在圖中, Book是一種的PrintedDocument,以及PaperbackBook是一種的book。
圖中的便箋內的一個項目: Book是這兩個衍生的類別 (從PrintedDocument) 和基底類別 (PaperbackBook衍生自Book)。 這類類別階層架構的骷髏宣告是以下列的範例所示:
// deriv_SingleInheritance.cpp
// compile with: /LD
class PrintedDocument {};
// Book is derived from PrintedDocument.
class Book : public PrintedDocument {};
// PaperbackBook is derived from Book.
class PaperbackBook : public Book {};
PrintedDocument會被視為 「 直接基底 」 類別,以Book。 它是以 「 間接基底 」 類別PaperbackBook。 不同的是出現在類別宣告的基底清單中的直接基底類別,並不會間接基底。
每一個類別衍生的基底類別衍生的類別宣告之前宣告。 它不是足夠來提供向前參考宣告的基底類別。 它必須是完整的宣告。
在上述範例中,存取規範公用用。 公用、 受保護,以及私用繼承的意義述成員存取控制。
類別可以當做許多的特定類別的基底類別,如下圖所示。
導向非循環圖形的範例
在圖表中,如上所示,稱為"導向非循環圖形 」 (或"DAG"),部分類別是一種以上的衍生類別的基底類別。 然而,反向操作則不行: 沒有一個直接基底類別的任何給定衍生的類別。 圖中的圖表] 描述 「 單一繼承 」 結構。
注意事項 |
---|
導向非循環的圖形不是只用於單一繼承的。它們也用於描述多重繼承圖形。本主題涵蓋的多重繼承。 |
在繼承中,在衍生的類別會包含基底類別的成員,加上任何您新增新的成員。 如此一來,在衍生的類別可以參考的基底類別成員 (除非在衍生類別中,這些成員會重新定義)。 範圍解析運算子 (::) 可以用來參照的直接或間接基底類別成員,當這些成員有已經重新定義的衍生類別中。 請考量以下範例:
// deriv_SingleInheritance2.cpp
// compile with: /EHsc /c
#include <iostream>
using namespace std;
class Document {
public:
char *Name; // Document name.
void PrintNameOf(); // Print name.
};
// Implementation of PrintNameOf function from class Document.
void Document::PrintNameOf() {
cout << Name << endl;
}
class Book : public Document {
public:
Book( char *name, long pagecount );
private:
long PageCount;
};
// Constructor from class Book.
Book::Book( char *name, long pagecount ) {
Name = new char[ strlen( name ) + 1 ];
strcpy_s( Name, strlen(Name), name );
PageCount = pagecount;
};
請注意,對於Book,(Book::Book),具有存取權的資料成員中, Name。 在程式中,型別的物件Book您可以建立及使用方法如下:
// Create a new object of type Book. This invokes the
// constructor Book::Book.
Book LibraryBook( "Programming Windows, 2nd Ed", 944 );
...
// Use PrintNameOf function inherited from class Document.
LibraryBook.PrintNameOf();
如先前範例所示,類別成員和繼承的資料和函式使用完全相同。 如果類別實作Book的重新實作會呼叫PrintNameOf函式、 函式屬於Document類別可以呼叫使用範圍解析 (::) 運算子:
// deriv_SingleInheritance3.cpp
// compile with: /EHsc /LD
#include <iostream>
using namespace std;
class Document {
public:
char *Name; // Document name.
void PrintNameOf() {} // Print name.
};
class Book : public Document {
Book( char *name, long pagecount );
void PrintNameOf();
long PageCount;
};
void Book::PrintNameOf() {
cout << "Name of book: ";
Document::PrintNameOf();
}
指標,且對衍生類別的參考可以隱含轉換為指標,且其基底類別的參考是否可存取的、 模稜兩可的基底類別。 下列的程式碼會示範這個概念使用指標 (相同的原則套用至參考):
// deriv_SingleInheritance4.cpp
// compile with: /W3
struct Document {
char *Name;
void PrintNameOf() {}
};
class PaperbackBook : public Document {};
int main() {
Document * DocLib[10]; // Library of ten documents.
for (int i = 0 ; i < 10 ; i++)
DocLib[i] = new Document;
}
在上述範例中,建立不同的型別。 不過,因為這些型別都衍生自Document類別,沒有隱含轉換成Document *。 如此一來, DocLib是 「 異質性清單 」 (清單中哪一個無法所有物件都都屬於相同型別) 包含不同類型的物件。
因為Document類別有PrintNameOf函式,它可以列印在媒體櫃中,每個活頁簿的名稱,雖然它可能會省略某些類型的文件的特定資訊 (頁面計數的Book的位元組數字、 HelpFile,依此類推)。
注意事項 |
---|
強迫基底類別實作函式,例如PrintNameOf通常不是最佳設計。虛擬函式提供其他的設計替代方案。 |