更新: この例のshared_ptrはBoostのものに似ていますが、shared_polymorphic_downcast(またはdynamic_pointer_castまたはstatic_pointer_cast)をサポートしていません!
参照カウントを失うことなく、派生クラスへの共有ポインターを初期化しようとしています:
struct Base { };
struct Derived : public Base { };
shared_ptr<Base> base(new Base());
shared_ptr<Derived> derived;
// error: invalid conversion from 'Base* const' to 'Derived*'
derived = base;
ここまでは順調ですね。 C++が暗黙的にBase *をDerived *に変換するとは思っていませんでした。ただし、コードで表現される機能(つまり、ベースポインターをダウンキャストしながら参照カウントを維持する)が必要です。私の最初の考えは、Derivedへの暗黙的な変換が行われるようにBaseにキャスト演算子を提供することでした(ペダントの場合:ダウンキャストが有効であることを確認します、心配しないでください):
struct Base {
operator Derived* ();
}
// ...
Base::operator Derived* () {
return down_cast<Derived*>(this);
}
まあ、それは助けにはなりませんでした。コンパイラは私の型キャスト演算子を完全に無視したようです。 shared_ptr割り当てを機能させる方法はありますか?余分なポイント:Base* const
は? const Base*
わかりましたが、Base* const
?この場合、const
は何を指しますか?
dynamic_pointer_cast
を使用できます。 std::shared_ptr
でサポートされています。
std::shared_ptr<Base> base (new Derived());
std::shared_ptr<Derived> derived =
std::dynamic_pointer_cast<Derived> (base);
また、基本クラスでキャスト演算子を使用することはお勧めしません。このような暗黙のキャストは、バグやエラーの原因になる可能性があります。
-Update:タイプがポリモーフィックでない場合、std::static_pointer_cast
を使用できます。
boost::shared_ptr
を使用していると思います... dynamic_pointer_cast
またはshared_polymorphic_downcast
が必要だと思います。
ただし、これらには多相型が必要です。
Base* const
の種類は何ですか?const Base*
わかりましたが、Base* const
?この場合、const
は何を指しますか?
const Base *
は、定数Base
への可変ポインターです。Base const *
は、定数Base
への可変ポインターです。Base * const
は、可変のBase
への定数ポインターです。Base const * const
は、定数Base
への定数ポインターです。最小限の例を次に示します。
struct Base { virtual ~Base() { } }; // dynamic casts require polymorphic types
struct Derived : public Base { };
boost::shared_ptr<Base> base(new Base());
boost::shared_ptr<Derived> derived;
derived = boost::static_pointer_cast<Derived>(base);
derived = boost::dynamic_pointer_cast<Derived>(base);
derived = boost::shared_polymorphic_downcast<Derived>(base);
あなたの例がベース型のインスタンスを作成してキャストするのが意図的であったかどうかはわかりませんが、違いをうまく説明するのに役立ちます。
static_pointer_cast
は「やるだけ」です。これにより、未定義の動作(Base
に割り当てられて初期化されたメモリを指すDerived*
)が発生し、クラッシュまたはさらに悪い結果を引き起こす可能性があります。 base
の参照カウントが増加します。
dynamic_pointer_cast
はNULLポインターになります。 base
の参照カウントは変更されません。
shared_polymorphic_downcast
は静的キャストと同じ結果になりますが、アサーションをトリガーし、むしろ成功したように見え、未定義の動作につながります。 base
の参照カウントが増加します。
(dead link) を参照してください:
static_cast
を使用するかdynamic_cast
を使用するかを決定するのが少し難しい場合があり、両方の世界を少し持ってほしいと思うでしょう。 dynamic_castには実行時のオーバーヘッドがあることはよく知られていますが、安全ですが、static_castにはオーバーヘッドがまったくありませんが、静かに失敗する可能性があります。デバッグビルドでshared_dynamic_cast
を使用し、リリースビルドでshared_static_cast
を使用できるとしたら、どんなに素晴らしいでしょう。まあ、そのようなものは既に利用可能であり、shared_polymorphic_downcast
と呼ばれます。
誰かがboost :: shared_ptrでここに来たら...
これは、派生Boostのshared_ptrにダウンキャストする方法です。 DerivedがBaseから継承すると仮定します。
boost::shared_ptr<Base> bS;
bS.reset(new Derived());
boost::shared_ptr<Derived> dS = boost::dynamic_pointer_cast<Derived,Base>(bS);
std::cout << "DerivedSPtr is: " << std::boolalpha << (dS.get() != 0) << std::endl;
「ベース」クラス/構造体に少なくとも1つの仮想関数があることを確認してください。仮想デストラクタも機能します。