C ++では、デコレータソフトウェアデザインパターンは、インスタンス化できるタイプがある場合に使用するのに適していますが、一部の機能を追加するためにそのクラスから継承できないという制限があります。
私の質問は、C ++でクラスのインスタンスを持つことはできるが、同じクラスから継承できない場合はどうなるでしょうか。
C ++では、デコレータソフトウェアデザインパターンは、インスタンス化できるタイプがある場合に使用するのに適していますが、一部の機能を追加するためにそのクラスから継承できないという制限があります。
私の質問は、C ++でクラスのインスタンスを持つことはできるが、同じクラスから継承できない場合はどうなるでしょうか。
C++ コンパイラが C++11 と互換性がある場合、クラスを宣言してクラスをfinal
非継承にすることができます。
class A final
{
};
キーワードをサポートするコンパイラにアクセスできない場合はfinal
、コンストラクタを非公開にし、静的ファクトリ メソッドを使用する必要があります。
class A
{
A() {}
public:
A createA() { return A(); }
};
ファクトリを必要としないようにするために C++03 で使用できるトリックがあります。
struct Final;
struct FinalHelper {
friend struct Final;
private:
FinalHelper() {}
~FinalHelper() {}
};
struct Final : private virtual FinalHelper {
Final() {}
};
これは、誰かが基本クラスとして使用することを実際に妨げるものではありませんがFinal
、派生クラスを構築または破棄することを妨げます。その理由は、最も派生したクラスが仮想ベースの構築と破棄を担当しますが、 のコンストラクターとデストラクタはFinalHelper
、そうでない限り、最も派生したクラスではアクセスできないためですFinal
。
もちろん、これにはおそらく実行時のメモリ コストがかかります (仮想ベースの場合)。
通常、そのようなトリックは無意味です。C++ はプログラマーがドキュメントを読むことに依存しているため、組み込みのfinal
メカニズムは問題ありませんが、ランタイム コスト (仮想ベースの場合) やユーザビリティ コスト (ファクトリ関数の場合) を負担したくありません。たとえば、一部のコンテナー メンバー関数での使用に影響する) は、ドキュメントを強制するためだけです。
したがって、型は、それらが基本クラスとして使用されることを意図しているかどうかを文書化する必要があり、その文書化を無視するユーザーは自分自身を責めるだけです。