C++設計は継承できないクラスを実現する
5585 ワード
C++はJavaとは異なり、Javaではfinalキーワードで修飾されたクラスは継承されず、C++は継承されないクラスを実現できるが、自分で実現する必要がある.
クラスが継承されないようにするには、子クラスが親クラスの部分を構築できないようにすることが最善です.この場合、子クラス全体をインスタンス化できません.C++では、子クラスのコンストラクション関数が親クラスのコンストラクション関数を自動的に呼び出し、子クラスのコンストラクション関数も親クラスのコンストラクション関数を自動的に呼び出すので、クラスのコンストラクション関数とコンストラクション関数をprivate()関数として定義すれば、クラスが彼から継承しようとすると、コンストラクション関数、コンストラクション関数を呼び出そうとするとコンパイルエラーが発生するに違いありません.この場合、クラスは継承されません.
しかし、privateのコンストラクション関数とコンストラクション関数ではクラスのインスタンスが得られず、静的クラスを定義することでクラスのインスタンスを作成および解放できるという問題が発生します.
プログラムの例は次のとおりです.
前例ではFinalClass 1というクラスは継承できませんが、この方法で得られたインスタンスはすべてスタック上にあり、プログラマーが手動で解放する必要があります.
この限界を考慮して,次のクラスを設計した.
前の例のFinalClass 2クラスは、スタック上でもスタック上でもインスタンスを作成できる一般的なクラスとは何の違いもありません.一方、MakeFinalのコンストラクション関数とコンストラクション関数はプライベートですが、クラスFinalClass 2はその友元関数であるため、FinalClass 2でMakeFinalのコンストラクション関数とコンストラクション関数を呼び出してもコンパイルエラーは発生しません.
FinalClass 2クラスの場合、クラスを継承してインスタンスを作成すると、コンパイルエラーが発生します.プログラムコードの例は次のとおりです.
FinalClass 2はクラスMakeFinal虚から継承されているため、Tryのコンストラクション関数を呼び出すとFinalClass 2を直接スキップし、MakeFinalのコンストラクション関数を直接呼び出す.ただしクラスTryはMakeFinalの友元ではないため、プライベートなコンストラクタを呼び出すことはできません.したがって、FinalClass 2から継承しようとするクラスは、インスタンス化されるとコンパイルエラーが発生するため、FinalClass 2は継承できません.
クラスが継承されないようにするには、子クラスが親クラスの部分を構築できないようにすることが最善です.この場合、子クラス全体をインスタンス化できません.C++では、子クラスのコンストラクション関数が親クラスのコンストラクション関数を自動的に呼び出し、子クラスのコンストラクション関数も親クラスのコンストラクション関数を自動的に呼び出すので、クラスのコンストラクション関数とコンストラクション関数をprivate()関数として定義すれば、クラスが彼から継承しようとすると、コンストラクション関数、コンストラクション関数を呼び出そうとするとコンパイルエラーが発生するに違いありません.この場合、クラスは継承されません.
しかし、privateのコンストラクション関数とコンストラクション関数ではクラスのインスタンスが得られず、静的クラスを定義することでクラスのインスタンスを作成および解放できるという問題が発生します.
プログラムの例は次のとおりです.
1 class FinalClass1
2 {
3 public:
4 static FinalClass1* GetInstance()
5 {
6 return new FinalClass1;
7 }
8
9 static void DeleteInstance(FinalClass1* pInstance)
10 {
11 delete pInstance;
12 pInstance = 0;
13 }
14
15 private:
16 FinalClass1(){}
17 ~FinalClass1(){}
18 };
前例ではFinalClass 1というクラスは継承できませんが、この方法で得られたインスタンスはすべてスタック上にあり、プログラマーが手動で解放する必要があります.
この限界を考慮して,次のクラスを設計した.
1 template <typename T> class MakeFinal
2 {
3 friend T;
4 private:
5 MakeFinal(){}
6 ~MakeFinal(){}
7 };
8
9 class FinalClass2 : virtual public MakeFinal<FinalClass2>
10 {
11 public:
12 FinalClass2(){}
13 ~FinalClass2(){}
14 };
前の例のFinalClass 2クラスは、スタック上でもスタック上でもインスタンスを作成できる一般的なクラスとは何の違いもありません.一方、MakeFinal
FinalClass 2クラスの場合、クラスを継承してインスタンスを作成すると、コンパイルエラーが発生します.プログラムコードの例は次のとおりです.
1 class Try : public FinalClass2
2 {
3 public:
4 Try(){}
5 ~Try(){}
6 };
7
8 Try temp;
FinalClass 2はクラスMakeFinal