web-dev-qa-db-ja.com

std :: shared_ptrの基本クラスへのアップキャスト-最良の方法?

どの変換が優れていますか、そして違いは何ですか?

class Base
{};

class Derived : public Base, public std::enable_shared_from_this<Derived>
{};

int main(int argc, const char * argv[])
{
    std::shared_ptr<Base> ptr1 = std::dynamic_pointer_cast<Base>(std::shared_ptr<Derived>(new Derived())); // version 1
    std::shared_ptr<Base> ptr2 = std::shared_ptr<Derived>(new Derived()); // version 2
    return 0;
}
15
Piotr Wach

shared_ptrの他のユースケースと同様に、make_sharedを手動で作成するのではなく、shared_ptrを使用することをお勧めします。

std::shared_ptr<Base> ptr2 = std::make_shared<Derived>();

これは基本的にバージョン2に加えて、 make_sharedのさまざまな利点 です。

バージョン1は、多くの不要な処理を実行します。最初に一時的なshared_ptr<Derived>を作成し、次にその内容を基本クラスポインタにdynamic_castします(ここではstatic_castで十分です)。そのポインタを別のshared_ptr<Base>に格納します。したがって、不要なランタイム操作がたくさんありますが、バージョン2よりも型の安全性に関する利点はありません。

16
ComicSansMS

2つ目は、明示的なキャストの使用を避けながら、実際のポインターで行われることの正確な転置であるため、より意味があります。

Base* ptr = new Derived();

別のオプションは、 std::make_shared テンプレートパラメータとしてDerivedを指定します。つまり:

std::shared_ptr<Base> ptr2 = std::make_shared<Derived>();
3
JBL

最も明白な答えは言及されていないようですので、完全を期すためにそれを追加します。

キャストは必要ありません。それを実現するための最良の方法は次のとおりです。

#include <memory>

class Base 
{};

class Derived : public Base, public std::enable_shared_from_this<Derived>
{};

int main(int argc, const char * argv[])
{
     std::shared_ptr<Derived> ptr1 = std::make_shared<Derived>();
     std::shared_ptr<Base> ptr2 = ptr1; // no CAST NEEDED HERE AS YOU SEE :)
     return 0;
}

この場合、enable_shared_from_thisから派生しても何も変更されません。次のクラスを使用することもできます(コードを少し読みやすくします)

class Base 
{};

class Derived: public Base
{};

もちろん、実装の詳細はわかりません。そのため、enable_shared_from_thisから派生する必要がある可能性が非常に高くなります。

0
CoffeDeveloper