すべての派生 C++/CLI クラスが基本クラスの ICloneable::Clone() メソッドをオーバーライドすることを確認するにはどうすればよいですか?
私はこれについて心配する必要があると思いますか?それとも、これは基本クラスの作成者の責任ではありませんか?
修正:申し訳ありませんが、基本クラスが非抽象クラスであることを忘れていました。
基本クラスで純粋仮想として宣言します。
class Base
{
...
viual void Clone() = 0;
};
これが基本クラスの責任であるかどうかはわかりませんが、ここでは継承ベースの契約の危険にさらされることはありません。
いずれにせよ、一部のクラスにメソッドを強制的にオーバーライドさせることができます。たとえば、「Clone()」を抽象クラスの純粋な仮想メンバーにすることで実行できます。
public ref class ClonableBase abstract
{
public:
virtual void Clone() = 0;
}
「abstract」と「=0;」に注意してください。抽象により、クラスは警告なしで純粋な仮想メンバーを含むことができます。は、このメソッドが純粋な仮想であることを意味します。つまり、本体が含まれていません。抽象クラスをインスタンス化できないことに注意してください。
今、あなたはすることができます
public ref class ClonableChild : public ClonableBase
{
public:
virtual void Clone();
}
void ConableChild::Clone()
{
//some stuff here
}
ClonableChild に Clone オーバーライドがない場合、コンパイラ エラーが発生します。
基本クラスが非抽象クラスの場合、コンパイル時に強制的にオーバーライドする方法はありません。おそらくできる最善のことは、次のようなものです。
virtual void Clone()
{
throw gcnew NotSupportedException();
}
これにより、派生クラスはメソッドをオーバーライドする必要があります。そうしないと、アプリケーションで NotSupportedException が発生します。これにより、少なくともテスト中に何かが間違っていることがすぐに明らかになります。Clone を正しくオーバーライドしていないクラスに遭遇したときにわかるように、何かを探す必要があります。派生クラスをどの程度制御できるかに応じて、これは堅牢性にとって重要になる可能性があります。
Clone() メソッドを抽象として宣言します。これは、親クラスに具体的な実装がある場合でも機能するはずです。
もちろん、そのようなことを強制する場合のリスクは、派生クラスの作成者が腹を立て、「とにかく Clone を使用するつもりはない」と言って、バイトごとのコピーのようなことをしたり、「これを返す」ことさえしたりすることです。エラーを取り除きます。
ハーブサッターでこれを読んでください。それはまさにあなたが求めているものです
熟考した後、私はこの解決策を見つけました:
Object^ BaseClass::Clone()
{
if(this->GetType() != BaseClass::typeid)
{
throw gcnew System::NotImplementedException("The Clone() method is not implemented for " + this->GetType()->ToString() + "!");
}
BaseClass^ base = gcnew BaseClass();
... // Copy the fields here
return base;
}
基本クラスの Clone() メソッドをオーバーライドしていない派生クラスのインスタンスを複製しようとすると、NotImplementedException がスローされます。
class Base
{
...
virtual void Clone() = 0;
};
正しい。
クローンのデフォルトの動作が必要な場合は、次を試してください。
class Base
{
...
virtual void Clone()
{
...
doClone();
...
};
...
private:
virtual void doClone() = 0;
};
修正:申し訳ありませんが、基本クラスが非抽象クラスであることを忘れていました。
この新しい観点から、誰かに Clone() をオーバーライドすることを強制したくないと確信しています。たとえば、派生クラスがフィールドを追加しない場合、おそらく独自の特殊な Clone() メソッドは必要ありません。
トーマスは正しいですが、そのクラスを抽象化する 1 つの方法は、純粋な仮想メソッドを定義することです。
これは、次のように言うことによって行われます。
virtual void Clone() = 0;
派生クラスが Clone を実装しない限り、それをインスタンス化することはできないため、クラスを有用なものにしたい場合、選択の余地はほとんどありません。