1

BCは から派生していますA。RTTI を使用せずに、から派生したクラスの 2 つのインスタンスAが同じクラスのインスタンスであるかどうか、つまりA* fooA* bar両方がインスタンスを指しているかどうかをテストできるようにしたいと考えています。B私の現在の解決策は次のようなものです:

class A {
protected:

    typedef uintptr_t Code;
    virtual Code code() const = 0;

}; // class A


class B : public A {
protected:

    virtual Code code() const { return Code(&identity); }

private:

    static int identity;

}; // class B


class C : public A {
protected:

    virtual Code code() const { return Code(&identity); }

private:

    static int identity;

}; // class C

このメソッドを使用すると、operator==簡単にテストできますfirst.code() == second.code()。すべての派生クラスがこのイディオムを繰り返す必要がないようにidentity、派生クラスからリテラルを削除し、コードが によって自動的に検出されるようにしたいと考えています。A繰り返しますが、私は RTTI を使用しないことを強く望んでいます。これを行う方法はありますか?

注:最近の質問[1][2]を見ましたが、これは重複していません。これらの投稿者は、派生クラスの内容をテストしたいと考えています。私は単に身元をテストしたいだけです。

4

4 に答える 4

3

車輪の再発明ではなく、RTTIを使用する必要があります。

RTTIを使用しないことを主張する場合は、CRTPと関数ローカル静的変数を使用して、すべての派生クラスに関数を書き込む必要をなくすことができます。私がウィキペディア用に書いたこのサンプルコードから適応してください:http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern#Polymorphic_copy_construction

もう1つの方法は、vtableポインターを(thisおよびポインター演算を介して)読み取ることですが、これはコンパイラーとプラットフォームの両方に依存するため、移植性はありません。

于 2010-02-11T06:31:29.947 に答える
2

あなたのアイデアは正しい方向に進んでいます。テンプレートを使用してボイラープレートを削除できるかもしれません:

class TypeTagged {
public:
  virtual Code code() const = 0;
}

template <class T>
class TypeTaggedImpl: public virtual TypeTagged {
public:
  virtual Code code() const { return Code(&id); }
private:
  static int id;
}

次に、クライアント クラスを次のように宣言するだけです。

class A: public TypeTaggedImpl<A> { ... }

class B: public A, public TypeTaggedImpl<B> { ... }

の異なるインスタンス化は、型が異なるフィールドを持ち、したがって異なる ID を持つことをTypeTagged意味します。id仮想基本型はcode、最も派生した型の が返されることを意味します。

于 2010-02-11T06:44:26.137 に答える
0

基本クラスをidコンストラクターパラメーターとして受け取りidentity()、基本クラス自体に関数を実装できます。その後、派生クラスでコードを繰り返す必要はありません。derived::derived(): base(0)派生クラス コンストラクターでは、次のようなサンプル コードを実行できます。

class A
{
public:
    A(int n) : m_id(n)
    {
    }
    virtual ~A(){}

    virtual int id() const 
    {
        return m_id;
    }

private:
    int m_id;
};

class B : public A
{
public:
    B() : A(0)
    {
    }
};
于 2010-02-11T06:14:15.647 に答える
-1

__FILE__ __LINE__コードとして両方のマクロを使用できます。
これにより、衝突の問題が回避されます。
この値を int にマップできます。

于 2010-02-11T06:14:41.087 に答える