92

基本クラスunique_ptrを取得する関数で to 派生クラスを使用しようとしています。unique_ptr何かのようなもの:

class Base {};

class Derived : public Base {};

void f(unique_ptr<Base> const &base) {}

…

unique_ptr<Derived> derived = unique_ptr<Derived>(new Derived);
f(derived);

この回答を正しく理解していれば、このコードは機能するはずですが、次のコンパイル エラーが発生します。

エラー C2664: 'f': パラメーター 1 を 'std::unique_ptr<_Ty>' から 'const std::unique_ptr<_Ty> &' に変換できません

IntelliSense: "std::unique_ptr<Derived, std::default_delete<Derived>>" から "const std::unique_ptr<Base, std::default_delete<Base>>" への適切なユーザー定義の変換が存在しません

ftakeに変更すると正常にunique_ptr<Derived> const &derived動作しますが、それは私が望むものではありません。

私は何か間違ったことをしていますか?これを回避するにはどうすればよいですか?

Visual Studio 2012 を使用しています。

4

4 に答える 4

95

次の 3 つのオプションがあります。

  1. 所有権を放棄します。これにより、関数呼び出し後に動的オブジェクトにアクセスせずにローカル変数が残ります。オブジェクトは呼び出し先に転送されました:

    f(std::move(derived));
    
  2. の署名を変更f:

    void f(std::unique_ptr<Derived> const &);
    
  3. 変数の型を変更します。

    std::unique_ptr<base> derived = std::unique_ptr<Derived>(new Derived);
    

    またはもちろん:

    std::unique_ptr<base> derived(new Derived);
    

    あるいは:

    std::unique_ptr<base> derived = std::make_unique<Derived>();
    
  4. 更新:または、コメントで推奨されているように、所有権をまったく譲渡しないでください。

    void f(Base & b);
    
    f(*derived);
    
于 2013-07-04T15:32:34.890 に答える
13

考えられる解決策は、引数の型を a に変更し、代わりにBase const*渡すことです。derived.get()での所有権の譲渡はないunique_ptr const<Base>&(そして は変更されていないunique_ptr) ため、 a に変更しBase const*ても意味は変わりません。


Herb Sutter は、Smart Pointer Parametersでスマート ポインター引数を長々と渡すことについて説明しています。リンクされた記事からの抜粋は、この正確な状況を指しています。

a を渡すのconst unique_ptr<widget>&は奇妙です。なぜなら、 aを介して呼び出し元のコードでライフタイムがたまたま管理されている のいずれnullかのみを受け入れることができ、呼び出し先は通常、呼び出し元のライフタイム管理の選択を気にするべきではないからです。パスはこれらのケースの厳密なスーパーセットをカバーし、呼び出し元がたまたま使用している有効期間ポリシーに関係なく、「<code>null または a 」を受け入れることができます。widgetunique_ptrwidget*widget

于 2013-07-04T15:52:14.227 に答える
-1

もう 1 つの方法は、 の署名を変更しfて、少し異なる方法で使用することです。

void f(Base* base_ptr) {
    // take ownership inside the function
    std::unique_ptr<Base> base {base_ptr};
    // ...
}

// ...
auto derived = std::make_unique<Derived>();
f(derived.release());  // release ownership
于 2021-07-14T11:45:44.127 に答える