1

プロトタイプパターンを実装するクラスの階層があり、 移動セマンティクスを使用してオブジェクトのディープコピーを制限したいと思います。move()元のオブジェクトが不要になるという意味のメンバー関数を使用してパターンを適合させようとしました。これが私がこれまでに持っているものです:

#include <iostream>
#include <utility>
#include <vector>

struct base
{
    virtual ~base() { }
    virtual base* clone() const = 0;
    virtual base* move() = 0;
};

struct derived1 : public base
{
    derived1()                { std::cout << "derived1::derived1()\n"; }
    derived1(const derived1&) { std::cout << "derived1::derived1(const derived1&)\n"; }
    derived1(derived1&&)      { std::cout << "derived1::derived1(derived1&&)\n"; }

    virtual ~derived1() { }

    virtual base* clone() const { return new derived1(*this); }
    virtual base* move()        { return new derived1(std::move(*this)); }
};

struct derived2 : public base
{
    derived2()                { std::cout << "derived2::derived2()\n"; }
    derived2(const derived2&) { std::cout << "derived2::derived2(const derived2&)\n"; }
    derived2(derived2&&)      { std::cout << "derived2::derived2(derived2&&)\n"; }

    virtual ~derived2() { }

    virtual base* clone() const { return new derived2(*this); }
    virtual base* move()        { return new derived2(std::move(*this)); }
};

std::vector<base*> vec;

void foo(const base& obj)
{
    vec.push_back(obj.clone());
}

void foo(base&& obj)
{
    vec.push_back(obj.move());
}

int main()
{
    derived1 d1;
    derived2 d2;

    foo(d1);
    foo(d2);
    foo(derived1());
    foo(derived2());
}

実行すると、優れたコンストラクターが使用されていることがわかります。

derived1::derived1()
derived2::derived2()
derived1::derived1(const derived1&)
derived2::derived2(const derived2&)
derived1::derived1()
derived1::derived1(derived1&&)
derived2::derived2()
derived2::derived2(derived2&&)

これまでのところ、それは良さそうです。これが右辺値参照の標準準拠の使用法であるかどうかはわかりません。それが望ましくない結果を生むとは思わなかった点はありますか?

4

1 に答える 1

1

繰り返しメソッドの定義については、CRTPを好みます。あなたの場合、私は次のように宣言します:

template<typename TDerived>
class virtually_clonable : public base
{
public:
    virtual base* clone() override
    {
        return new TDerived(*AsDerived());
    }

    virtual base* move() override
    {
        return new TDerived(std::move(*AsDerived()));
    }
private:
    TDerived* AsDerived()
    {
        return static_cast<TDerived*>(this);
    }
};

そして、クラスを実装している間:

class derived1 : public virtually_clonable<derived1>
{
public:
/* your ctors goes here*/
/* no need to implement clone/move again */
};

class derived2 : public virtually_clonable<derived2>
{
public:
/* your ctors goes here*/
/* no need to implement clone/move again */
};

ところで、shared_ptr生のポインターの代わりにオブジェクトを返したい場合があります。これは通常、 ではなく複製可能な型の場合ですunique_ptr

于 2013-01-31T23:39:56.730 に答える