単一継承
単一継承 「」では継承クラスの一般的な形式は 1 種類の基本クラスだけがあります。関係を次の図に示すことを検討してください。
単純な単一継承グラフ
通常の図に固有の流れに注意してください。ほとんどのクラス階層のデザインにあるもう一つの一般的な属性は派生クラスは基本クラスとのリレーションシップ 「の」種類があります。図ではBook は PrintedDocument 型でありPaperbackBook は book の型です。
図のメモの 1 つが他の項目 : 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 」 (または 「」) をクラスの一部の場合複数の派生クラスの基本クラス指示します。ただし逆方向ではありません : true 特定の派生クラスでは1 台の直接基本クラスがあります。図のグラフは単一継承 「」の構造を示しています。
[!メモ]
非循環有向グラフは単一継承に一意ではありません。また多重継承グラフを示すために使用されます。このトピックでは 多重継承 で説明します。
継承は派生クラスでは追加した新しいメンバーと基本クラスのメンバーも含まれます。したがって派生クラス (これらのメンバーを派生クラスで再定義する) 基本クラスのメンバーを参照できます。これらのメンバーは派生クラスで定義し直されたらスコープ解決演算子 () が :: 直接または間接基本クラスのメンバーを参照するために使用できます。次の例について考えます。
// 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();
前の例に示すようにクラス メンバーと継承されたデータは関数と同じように使用されます。PrintNameOf の関数の reimplementation クラスの Book の呼び出しの実装が :: スコープ解決演算子 () 演算子を使用して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 などの関数を実装するための基本クラスを強制的には多くの場合最も適切なデザインではありません。仮想関数 その ほかのデザイン方法が用意されています。