派生型の_shared_ptr
_を基本型の_shared_ptr
_をとる関数に渡すのに最適な方法は何ですか?
通常、不要なコピーを避けるために_shared_ptr
_ sを参照で渡します。
_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つの理由で次善のようです。
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)
。 循環参照 を避けるための通常のアドバイスが適用されます。
詳細については、Herb Sutterの Back to Basics talk を参照してください。
Base
とDerived
は共変であり、それらへの生のポインターはそれに応じて動作しますが、_shared_ptr<Base>
_と_shared_ptr<Derived>
_はnot共変です。 _dynamic_pointer_cast
_は、この問題を処理するための正しい最も簡単な方法です。
(編集: _static_pointer_cast
_は、派生からベースにキャストするため、より適切です。これは安全で、ランタイムチェックを必要としません。以下のコメントを参照してください。)
ただし、foo()
関数がライフタイムの延長に参加したくない場合(または、オブジェクトの共有所有権に参加したい場合)は、_const Base&
_を受け入れるのが最善です。 foo()
に渡すときに_shared_ptr
_を逆参照します。
_void foo(const Base& base);
[...]
shared_ptr<Derived> spDerived = getDerived();
foo(*spDerived);
_
余談ですが、_shared_ptr
_型は共変にできないため、_shared_ptr<T>
_の型を返す場合、共変の戻り型間の暗黙的な変換の規則は適用されません。
あなたが一生懸命やっているように聞こえます。 shared_ptr
はコピーが安価です。それが目標の1つです。参照によってそれらを渡すことは、実際にはあまり達成されません。共有したくない場合は、生のポインタを渡します。
そうは言っても、これを行うには2つの方法があります。
foo(shared_ptr<Base>(bar));
foo(static_pointer_cast<Base>(bar));
これは、派生クラスでpublic継承を指定するのを忘れた場合にも発生します。つまり、私のように次のように記述します。
class Derived : Base
{
};
また、派生クラスの完全な宣言を含むヘッダーファイルの#include
がソースファイルにあることを確認します。
この問題がありました。 std::shared<derived>
はstd::shared<base>
にキャストされません。ポインタを保持できるように両方のクラスを前方宣言しましたが、#include
を持っていなかったため、コンパイラは一方のクラスが他方から派生したことを確認できませんでした。