5

スマート ポインターはダウン キャストを処理しますか?そうでない場合、この制限を回避する安全な方法は何ですか?

私がやろうとしていることの例は、スマート ポインターを含む 2 つの STL ベクトル (たとえば) を持つことです。1 つ目は基本クラスへのスマート ポインターを含み、2 つ目は派生クラスへのスマート ポインターを含みます。スマート ポインターはカウントされて参照されます。たとえば、Boost の shared_ptrs と同様の動作ですが、手動でロールされます。例を提供するために作成したサンプルコードをいくつか含めました。

vector<CBaseSmartPtr> vecBase;
vector<CDerivedSmartPtr> vecDer;
...
CBaseSmartPtr first = vecBase.front();
vecDer.push_back(CDerivedSmartPtr(dynamic_cast<CDerived*>(first.get()));

同じオブジェクトを管理する 2 つのスマート ポインターで終わると思うので、これは私には安全ではないようです。トラックのどこかの時点で、これはおそらくオブジェクトへの参照を保持している間に、一方がオブジェクトを解放するという結果になるでしょう。

私が望んでいるがうまくいくとは思わないのは、同じオブジェクトを維持しながらまっすぐにダウンキャストすることです。

dynamic_cast<CDerivedSmartPtr>(first)

CBaseSmartPtr を使用し、使用時にのみダウンキャストするように 2 番目のコンテナーを変更する必要がありますか? 他の解決策はありますか?

4

5 に答える 5

5

スマート ポインターはダウンキャストを処理できますが、自動ではありません。また、const-correctness を取得するのは少し複雑になる可能性があります (私はインタビューの質問でスマート ポインターの実装を使用しましたが、テンプレートのトリックがいくつか含まれています)。しかし、スマート ポインターの多くのユーザーは、スマート ポインターを const 修飾された型でインスタンス化することは決してありません。

最初に正しくする必要があるのはカウンターです。smart_ptr<Base>と の間でカウンターを共有する必要がある場合があるためsmart_ptr<Derived>、カウンターの型は型引数に依存しないようにします。一般的に、これはとにかく大したことではありません。カウンターは単なる size_t であり、おそらくクラスにラップされています。(注: 代替のスマート ポインター デザインがありますが、質問はカウンターが使用されていることを強く示唆しています)

ベースへのキャストはかなり簡単です。したがって、smart_ptr には smart_ptr を取るコンストラクターが必要です。この ctor に、行を追加しますstatic_cast<T*>((U*)0);。これはコードを生成しませんが、T が U のベースでない場合 (モジュロ const 修飾) にインスタンス化を防ぎます。

逆の場合は、明示的なキャストにする必要があります。T のすべてのベースをプログラムで列挙することはsmart_ptr<T>できないため、から派生させることはできません。smart_ptr<Base1_of_T>, smart_ptr<Base2_of_T>, ...したがって、adynamic_cast<smart_ptr<T> >は機能しません。独自の を提供できますsmart_dynamic_cast<SPT>(smart_ptr<U> const& pU)。これは、 を返す関数として実装するのが最適SPTです。この関数では、単純にreturn SPT(dynamic_cast<SPT::value_type*>(&*pU)).

于 2009-09-02T07:46:58.550 に答える
2

必要なプロパティは、指定された型の共分散です。つまり、D が B の場合、 が必要ですsmartptr<D> isa smartptr<B>。これが C++ でエレガントにサポートされているとはまったく思いませんが、いつものように、テンプレート/オーバーロードのハックが利用可能です。

http://www.boost.org/doc/libs/1_39_0/libs/smart_ptr/pointer_cast.htmlは、通常および boost::smart_ptr で動作する動的キャストを提供します。Boost だけを使用したくない場合は、実装から学ぶ必要があります。

于 2009-09-02T00:42:21.767 に答える
1

ブースト メーリング リストのいずれかで、こちらのスレッドに従ってください。これは、boost::shared_ptr の場合にスマート ポインター ダウンキャストを実装する方法を示しています。HTH

于 2009-09-02T03:50:32.863 に答える
0

のような通常のスマート ポインターはstd::auto_ptr、STL コンテナーで使用するのは安全ではありません。これは、STL がスマート ポインターのインスタンスを相互に割り当て、内部でデータをコピーするときに所有権が移動するためです。boost::shared_ptr代わりに、参照カウントを内部的に実装するようなものを使用して、オブジェクトを参照するスマート ポインター インスタンスの数に関係なくオブジェクトが存続するようにする必要があります。独自のスマート ポインター型を作成している場合は、同様の参照カウントを実装する必要があります。

于 2009-09-02T00:10:16.663 に答える
0

Microsoftのページでこれを見つけました:

    std::shared_ptr<base> sp0(new derived); 
    std::shared_ptr<derived> sp1 = 
    std::dynamic_pointer_cast<derived>(sp0); 
于 2011-10-30T10:56:06.600 に答える