0

タイトルが示すように、実行時の型チェックの高速な方法を探しています。私の問題を説明するために、次のようなクラス階層があるとします。

      Base
     /     \
    A       D
   / \     / \
  C   B   F   E
       \ /
        G

これらのクラスはすべて共通のタスクを共有するため、私のプログラムでは、任意のクラスのすべてのインスタンスを Base_ptr として 1 つのリストに保持します。ある時点で、一部の派生クラスは、別のクラスのインスタンスの存在について知る必要があります。これまでのところ、私は dynamic_cast と typeid()-operator について知っていますが、どちらにもいくつかの重大な欠点があります。

  1. 型に互換性がない場合、dynamic_cast は多くの処理時間を消費します (たとえば、E のインスタンスを C にキャストしようとする)。
  2. typeid() は「isTypeOrSubtype」の場合には機能しません。たとえば、D のすべてのインスタンスまたは D から派生したものが必要です (したがって、Es、Fs、および Gs も必要です)。

理想的な解決策は、ある種の「isTypeOrSubtype」テストと、このテストが正常に返された場合のキャストのみです。いくつかのマクロ定義と事前に計算されたクラス名ハッシュを使用した独自のアプローチを得ましたが、それは非常に醜く、ほとんど保守できません。そのため、1 秒間に 2000 万回以上チェックできる、動的な型とサブタイプのチェックのクリーンで高速な方法を探しています。

4

4 に答える 4

0

これはRTTIを回避するための別のアプローチですが、動的なタイプ/サブタイプチェックの高速な方法に対する実際の答えではないため、私は自分の質問に対する答えを書きました。これはまだきれいな解決策ではありませんが、今まで考えられる最善の方法です。

この階層のすべてのクラスが次の特性を備えている場合、RTTI のほとんどをスキップできます。

  1. すべてのクラスにはプライベート メンバーが必要です。static SecureVector<[class]*> s_Instances;ここSecureVector<T>で、 はスレッド セーフなベクトルです。
  2. すべてのコンストラクターの最後で、s_Instances.push_back(this);そのクラスの新しく作成されたインスタンスを追跡するために呼び出す必要があります
  3. デストラクタの先頭で、s_Instances.erase(this);このインスタンス参照を削除するために呼び出す必要があります
  4. すべてのクラスにはパブリック関数が必要です:static const SecureVector<[class]*>& Instances() { return s_Instances; }このクラスまたは派生クラスのすべてのインスタンスを含む変更不可能なベクトルを取得する

これが行うことは、コンストラクターが呼び出されるたびに、インスタンスが自身のインスタンス リストに追加されることです。派生クラスがスーパー コンストラクターを呼び出すと、スーパー クラスは自身をそれぞれのインスタンス リストに追加します。たとえば、上記の階層で 100 個のインスタンスをランダムに作成すると、BaseクラスInstances()ベクトルには常に 100 個のエントリが存在します。

コードでは、これは次のようになります。

class Base
{
    static SecureVector<Base*> s_Instances; // 1. condition

public:

    Base() 
    {
        s_Instances.push_back(this);    // 2. condition
    }

    ~Base()
    {
        s_Instances.erase(this);    // 3. condition
    }

    static const SecureVector<Base*>& Instances() { return s_Instances; } // 4. condition
};

4 つの条件を手動で (またはマクロなどで) 追加する必要があるため、これは回避策と同じです。

于 2013-09-11T23:47:35.577 に答える
-1

dynamic_castこれには素晴らしく機能します!

Base *instance = //get the pointer from your collection;
A* ap = dynamic_cast<A*>(instance);
D* dp = dynamic_cast<D*>(instance);

if(ap) {
    //instance is an A or a subclass of A
}
if(dp) {
    //instance is a D or a subclass of D
}

これは、より具体的なチェックにも機能します。したがって、必要なタイプを確認できます。

于 2013-09-11T01:39:52.310 に答える