2011-12-19 7 views
9

リファレンスカウントを実装するC++クラスがあり、このクラスのすべてのユーザーが、このクラスから仮想的にのみ継承して、複数の参照カウンタでオブジェクトが終了しないようにします。特定のクラスの仮想継承を検出してアサートする方法はありますか?

私は、コンパイル時または少なくとも実行時にいずれかのこの需要量を主張するいくつかの方法をしたいと思います。

これを達成する方法はありますか?

答えて

5

私は、クラスをラップする最も簡単な選択肢になると思います。 RefCounterから直接継承するのではなく、中間クラスを作成します。

struct RefCounterVirtPrivate_ 
{ 
    int count; 

    RefCounterVirt() 
     : count(0) 
    { } 
}; 

struct RefCounter : public virtual RefCounterVirtPrivate_ 
{ 
}; 

struct A : public RefCounter { }; 
struct B : public RefCounter { }; 
struct C : public A, public B { }; 

その後、すべてが仮想継承を気にする必要なしRefCounterから継承することができます。既存のコードを変更する必要はありません。RefCounterの仮想継承自体は無害です。当然の

これは、人々が直接RefCounterVirtPrivate_から継承しません保証するものではありませんが、私はそれを明らかに名前を与えてくれた理由です。誤ってこれを行うことは、virtualというキーワードを忘れるよりも難しくなります。

0

これは、いくつかの策略で可能であってもよいが、影響を考慮する必要があります。あなたはその参照カウンタがこれまでにゼロに達した場合、オブジェクトがすぐに自己破壊する必要がポリシーを設定しています。それはオブジェクトの実装にdelete this;を呼び出したときに

アプリケーションに応じて、すなわち唯一の具体的な実装がに表示させた(基底クラスでadd_ref()release()抽象的機能を持って、正確な時間を残しておきたいかもしれませんすべてのインタフェースvtableが適切なサンクを持つ)、具体的なクラスに参照カウントを維持する負担をかける。

+0

実はこのクラスは 'すべての回でthis'自体を削除しないので、私は'のAddRef() '/'リリース() 'でチェックを行うことができます。そのトリッキーは大歓迎です。 – sharptooth

9

これは何ですか?

struct RefCounter { 
    template <typename T> 
    RefCounter(T *) { 
     BOOST_STATIC_ASSERT(boost::is_virtual_base_of<RefCounter, T>); 
    } 
}; 

struct GoodClass : virtual RefCounter { 
    GoodClass() : RefCounter(this) {} 
}; 

struct BadClass : RefCounter { 
    BadClass() : RefCounter(this) {} 
}; 

それは派生型をキャプチャするために、しかし、コンストラクタにthisを渡す必要がおよそ残念です。もちろん、意図的に鈍ったユーザーはthis以外のものを渡すことでそれを覆す可能性があります。

+0

'this'の代わりにCRTPを使うこともできますが、あなたの解決策は良いと思います。 – sbi

+0

@sbi:私はと考えているが、その後、 'RefCounter 'と 'RefCounter '異なるクラスになり、そのため彼らは仮想であっても、あなたはまだ、複数のrefcounter基底クラスのサブオブジェクトで終わることができました。 –

+0

クラスが2つの基底から継承し、1つの基底が実質的に 'RefCounter'から継承し、もう1つが実質的に継承しない場合、これは動作しますか? – sharptooth