2

たとえば、このクラスに (実行時に) 仮想コンストラクターがあることを確認する方法はありますか?

   TMyClass = class(TObject)
     MyStrings: TStrings;
     constructor Create; virtual;   
   end;

たとえば、このコードでは、Clazz によって参照されるクラスに仮想コンストラクターがあるかどうかをテストしたいと思います。

procedure Test;
var
  Clazz: TClass;
  Instance: TObject;
begin
  Clazz := TMyClass;
  Instance := Clazz.Create;
end;

Delphi 6 から 2009 で動作する RTTI を使用するなど、簡単な解決策はありますか?

4

3 に答える 3

3

ご存知のように、考えれば考えるほど、私が与えた答えが受け入れられなくなるのが好きではなくなります。問題は、記述されたコードはコンパイル時に既知の情報しか処理できないことです。ClazzがTClassとして定義されている場合、Clazz.CreateをTMethodに配置すると、常にTObject.Createへのメソッドポインターが提供されます。

Clazzを「TMyClassのクラス」として定義してみることができます。つまり、そこにはすでに仮想コンストラクターがあるので、そのコンストラクターをオーバーライドする、到達可能な最高レベルのコンストラクターを提供します。しかし、あなたのコメントから、あなたが見つけようとしているのは、仮想構造を壊す非仮想コンストラクター( reintroduce;を使用)であるように見えます。ほとんどの場合、これが問題になる可能性があるファクトリパターンを使用しています。

これに対する唯一の解決策は、RTTIを使用して、クラスに実際に接続されているコンストラクターを見つけることです。「Createという名前のメソッド」のメソッドポインタを取得して、他の回答で説明したトリックで使用できます。これを行うには、ベース仮想コンストラクターを公開済みとして宣言する必要があります。これにより、それをオーバーライドするすべてのメソッドも強制的に公開されます。問題は、誰かがまだreintroduceを使用できることです。公開されていないコンストラクターを上位に宣言すると、スキームがクラッシュします。子孫クラスが何をするかについての保証はありません。

この質問に対する技術的な解決策はありません。実際に機能するのは教育だけです。ユーザーは、このクラスがファクトリによってインスタンス化されること(または仮想コンストラクターが必要な理由が何であれ)、および派生クラスにコンストラクターを再導入すると、問題が発生する可能性があることを知っておく必要があります。この趣旨のメモをドキュメントに入れ、ソースコードにコメントを入れてください。それがあなたにできることのほとんどすべてです。

于 2009-04-26T20:05:07.263 に答える