参照カウントを実装する C++ クラスがあり、このクラスのすべてのユーザーがこのクラスから仮想的にのみ継承するようにして、オブジェクトが複数の参照カウンターを持たないようにします。
コンパイル時または少なくとも実行時に、この要件をアサートする何らかの方法が必要です。
それを達成する方法はありますか?
参照カウントを実装する C++ クラスがあり、このクラスのすべてのユーザーがこのクラスから仮想的にのみ継承するようにして、オブジェクトが複数の参照カウンターを持たないようにします。
コンパイル時または少なくとも実行時に、この要件をアサートする何らかの方法が必要です。
それを達成する方法はありますか?
このようなもの?
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
ます。
クラスをラップするのが最も簡単なオプションだと思います。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
キーワードを忘れるよりも、誤ってこれを行う方が難しいです。
いくつかのトリックで可能になるはずですが、その影響を考慮してください。参照カウンターがゼロに達した場合にオブジェクトがすぐに自己破壊する必要があるというポリシーを設定しています。
delete this;
アプリケーションによっては、オブジェクトの実装を呼び出す正確な時間を残したい場合があります。つまり、基本クラスに抽象関数のみがadd_ref()
ありrelease()
ます(これにより、1つの具体的な実装が適切なサンクですべてのインターフェイスvtableに表示されます)参照カウントを維持する負担を具体的なクラスに課します。