2012-03-19 7 views
7

サブクラスが適切なスマートポインタを取得できるようにする解決策を見つける必要があります。サブクラスとget_shared_from_this()

class Parent : public enable_shared_from_this { 
    ... 
} 

class Child : public Parent { 
    public Child(){ 
    boost::shared_ptr<Parent> pointer=shared_from_this(); // should work 
    boost::shared_ptr<Child> pointer=shared_from_this(); // won't work. 

    ... 
} 

shared_from_this()を使用して正しいスマートポインタを取得するにはどうすればよいですか?

CONTEXT:

私は通知/リスナーのもののビットを書いている、といくつかのクラスが自然に通知から自身を登録し、登録解除する必要があります。例えば、

class Body : extends Listener<BodyMessage>{ // listen for BodyMessage messages 
    public: 
    Body() { 
     Notifier<BodyMessage>::register(this); // register with the appropriate notifier 
    } 

    virtual ~Body { 
     Notifier<BodyMessage>::unregister(this); // unregister 
    } 

    bool notify(BodyMessage m){ ... } 

    ... 
} 

は、通常、私はちょうどこのポインタを使用して、すべてがうまくなります。 Notifierにテンプレートを使用させるので、メッセージを聞きたいものにのみメッセージを渡すことができます。

しかし、私はスマートポインタを使いたいです。通知は次のようになります場合:

template<typename t> 
class Notifier { 
    public: 
    static void register<boost::shared_ptr<Listener<t>>> boost::shared_ptr<Listener<t>> listener); 

    ... 
} 

その後、私はこれ以上にこのポインタを使用することはできません。自然に、私はボディ拡張enable_shared_from_thisを作成しました:

class Body : public boost::enable_shared_from_this, public Listener<BodyMessage> { 
    public: 
    Notifier<BodyMessage>::register(get_shared_ptr()); 
    ... 
} 

そして、それはボディーのために働くようです。私はshared_pointerをキャストすることはできませんので

class BodyChild : public Body { 
    public: 
    BodyChild(){ 
     Notifier<BodyMessage>::register(get_shared_ptr()); 
} 

可能性:それはサブクラス体の(あるいは、少なくとも、それはしていないようです)のために、しかし、動作しません。だから、私は

    • が(これらのリスナーが他のスマートポインタの文脈でも使用されているので)私はリスナーの共有ポインタを使用することができます解決策を作ることができ、私が使用して、通知とリスナーをテンプレートすることができますテンプレートのメッセージタイプそのものなので、特定のメッセージを聞くのが非常に簡単です。したがって、メッセージをデコードする必要はありません。
    • は簡単ですか?

    私は他のアイデアにも触れていますが、これがうまくいくと私は興奮します。

  • +0

    おかしい(ケーニッヒ・ルックアップにstatic_pointer_cast感謝を修飾する必要が)、私は反対走っていない:thisは右の動的な型であるため

    、あなたはshared_from_this()の戻り値にboost::static_pointer_castを呼び出すことができます今日はこの非常に問題です。 Observerパターンにスマートポインタを使用することは非常に良いアイデアであることが判明しました。また、 'boost :: signals'を使って自動的に半分の作業を行うこともできます(特に' scoped_connection'オブジェクトで)。 –

    +0

    あなたのnotifier/listenerシステムに 'std :: shared_ptr'が必要/必要なのはなぜですか?リスナーが実際にノーティファイヤーによって所有されていなければならないので、ノーティファイヤーがすべて消えたら、それらは破壊されますか?または、実際には、リスニングオブジェクトを所有し、インスタンス化と構築の世話をすることができる他のオブジェクトがありますか?そのようなシステムを構築するとき、私は実際には多くの制御を維持し、それをあきらめないことは非常に有益であることを発見しました。 – LiKao

    +0

    @LiKao:観測者パターンを書く1つの方法は、リスナーに通知機能を持たせ、破壊時にはunsuscribeすることです(shared_ptr + boost :: signalsは<50 LOCでこれを書くのに優れています)。逆に、この状況では非常にシンプルで固いものに固執すれば、より良いコードを書くのに役立つことがわかりました。 –

    答えて

    6

    スマートポインタをキャストすることで、Boostはこれを簡単にするためのテンプレートをいくつか用意しています。あなたは、例えば、 static_pointer_castdynamic_pointer_castを使用すると、ポインタを「スルー」することができます。

    boost::shared_ptr<Child> p = static_pointer_cast<Child>(shared_from_this()); 
    

    +1

    static_pointer_cast (...)は、この場合にはおそらく最良の方法です。ありがとう。オブジェクトのスマートポインタはコンストラクタが終了するまで「利用可能」ではないため、ノーティファイヤでスマートポインタを使用することはできません。 – whiterook6

    関連する問題