1. ホーム
  2. c++

[解決済み] shared_ptr<Derived>をshared_ptr<Base>として渡す。

2022-08-30 14:59:26

質問

を渡すのに最適な方法は何ですか? shared_ptr を受け取る関数に、派生型の shared_ptr を取る関数に変更できますか?

私は一般的に shared_ptr を参照で渡し、無駄なコピーを避けるようにしています。

int foo(const shared_ptr<bar>& ptr);

のようにしてもうまくいきません。

int foo(const shared_ptr<Base>& ptr);

...

shared_ptr<Derived> bar = make_shared<Derived>();
foo(bar);

を使うことができた。

foo(dynamic_pointer_cast<Base, Derived>(bar));

が、これは2つの理由から最適ではないようです。

  • A dynamic_cast は単純な派生からベースへのキャストには少し過剰なようです。
  • 私が理解しているように dynamic_pointer_cast は関数に渡すポインタのコピーを (一時的なものではありますが) 作成します。

もっと良い解決策はないのでしょうか?

後世のために更新します。

ヘッダーファイルの欠落の問題であることが判明しました。また、私がここで行おうとしていたことは、アンチパターンと考えられています。一般的に

  • オブジェクトのライフタイムに影響を与えない (すなわち、オブジェクトはその関数の間、有効であり続ける) 関数は、例えば int foo(bar& b) .

  • 以下のような機能 消費する オブジェクトを消費する (すなわち、与えられたオブジェクトの最終的な利用者である) 関数は、そのオブジェクトのために unique_ptr を値として取ります。 int foo(unique_ptr<bar> b) . 呼び出し側は std::move を関数に渡す必要があります。

  • オブジェクトのライフタイムを延長する関数は shared_ptr を値として取るべきです。 int foo(shared_ptr<bar> b) . を避けるようにという通常のアドバイス 循環参照 が適用されます。

ハーブ・サッターの バック・トゥ・ベーシックス をご覧ください。

どのように解決するのですか?

しかし BaseDerived は共変量で、それらへの生のポインタはそれに応じて動作します。 shared_ptr<Base>shared_ptr<Derived> ではない 共変である。そのため dynamic_pointer_cast はこの問題を処理するための正しくて最も簡単な方法です。

( 編集してください。 static_pointer_cast の方が適切でしょう。なぜなら、 derived から base にキャストしているので、安全であり、実行時のチェックも必要ないからです。以下のコメントを参照してください)。

しかし、もしあなたの foo() 関数が寿命の延長に参加したくない (むしろオブジェクトの共有所有権に参加したくない) 場合は const Base& を受け入れ shared_ptr に渡すときは foo() .

void foo(const Base& base);
[...]
shared_ptr<Derived> spDerived = getDerived();
foo(*spDerived);

余談ですが shared_ptr の型は共変できないので、共変の戻り値の型をまたぐ暗黙の変換のルールは shared_ptr<T> .