11

クローンパラダイムは、基本クラスタイプにキャストダウンせずに、派生クラスのコピーを作成するために使用されます。残念ながら、clone各サブクラスに(またはCRTPとのミックスインを使用して)実装する必要があります。

C ++ 11decltypeがこれを不要にする可能性はありますか?

以下のコードは実際にはコピーされていないと思いますoriginalが、単にそれへの参照を示しています。を使おうとするとnew decltype(*original)、次のエラーが発生します error: new cannot be applied to a reference type

cloneまだC++11に行く方法はありますか?または、RTTIを使用して基本クラスポインタから派生クラスオブジェクトをコピーする新しい方法はありますか?

#include <iostream>

struct Base
{
  virtual void print()
  {
    std::cout << "Base" << std::endl;
  }
};

struct Derived : public Base
{
  int val;
  Derived() {val=0;}
  Derived(int val_param): val(val_param) {}
  virtual void print()
  {
    std::cout << "Derived " << val << std::endl;
  }
};

int main() {
  Base * original = new Derived(1);
  original->print();

  // copies by casting down to Base: you need to know the type of *original
  Base * unworking_copy = new Base(*original);
  unworking_copy->print();

  decltype(*original) on_stack = *original;
  on_stack.print();
  return 0;
}
4

4 に答える 4

21

decltype静的構造です。すべてのC++タイピング構造と同様に、オブジェクトの実行時型を推測することはできません。decltype(*original)ただBase&です。

于 2012-05-03T02:43:04.950 に答える
3

decltype(その名前が示すように)それが適用される式の宣言されたタイプ(静的タイプ)を与えます。

decltype(*original)であるBase&ため、コードは次のように出力されます

Derived 1
Base
Derived 1

ただし、3番目のケースではコピーは作成されません。

クローン(またはパターンの変形)は、C++11で使用する方法です。

于 2012-05-03T02:44:57.827 に答える
3

decltype動的オブジェクトタイプを回復することはできず、回復しません。これは純粋に静的な構成です。

オブジェクトをコピーする魔法の方法はありません。正確な最終動的型のコンストラクターをどこかで呼び出す必要があります。

于 2012-05-03T02:55:33.827 に答える
2

クローンはまだC++11に行く方法ですか?または、RTTIを使用して基本クラスポインタから派生クラスオブジェクトをコピーする新しい方法はありますか?

非侵襲的なクローン作成に興味がある人のために、C ++ 11のラムダはいくつかの新しいクローン作成機能を提供しているようです。クローン作成の問題を考えると、オブジェクトの元のインスタンスを作成した人もレプリカの作成を支援できる人。すべてのオブジェクトが一部のによって製造されている場合を考えてみますFactory。この場合、通常のcreateインターフェースに加えて、工場にインターフェースを装備することができcloneます。たとえば、次のようになります。

#include <iostream>
#include <functional>
#include <memory>
#include <unordered_map>

template <typename BASE>
struct
Factory {
    private: using
    TCloneFn = std::function<std::shared_ptr<BASE>(BASE const * const)>;

    private:
    static std::unordered_map<BASE const*,TCloneFn> cloneFnMap;

    public: template <typename DERIVED_TYPE, typename...TS>
    static std::shared_ptr<BASE>
    create(TS...args) {
        BASE* obj = new DERIVED_TYPE(args...);
        const std::shared_ptr<BASE> pNewObj =
            std::shared_ptr<BASE>(
                obj,
                [&](BASE* p){
                    cloneFnMap.erase(p);
                    delete p;
                }
            );

        cloneFnMap[obj] = [&](BASE const * const orig){
            std::shared_ptr<BASE> pClone = create<DERIVED_TYPE>(std::ref(static_cast<DERIVED_TYPE const &>(*orig)));
            return pClone;
        };
        return pNewObj;
    }

    public: static std::shared_ptr<BASE>
    clone(std::shared_ptr<BASE const> original) {
        return cloneFnMap[original.get()](original.get());
    }
};

template <typename BASE> std::unordered_map<BASE const*,typename Factory<BASE>::TCloneFn> Factory<BASE>::cloneFnMap;

class Base {
    public: virtual ~Base() throw() {}
    public: virtual void whoAmI() const {
        std::cout << "I am Base instance " << this << "\n";
    }
};


class Derived : public Base {
    std::string name;
    public: Derived(std::string name) : name(name) {}
    public: Derived(const Derived&other) : name("copy of "+other.name) {
    }
    private: virtual void whoAmI() const {
        std::cout << "I am Derived instance " << this << " " << name << "\n";
    }
};

int main() {
    std::shared_ptr<Base> a = Factory<Base>::create<Derived>("Original");
    a->whoAmI();
    std::shared_ptr<Base> copy_of_a = Factory<Base>::clone(a);
    copy_of_a->whoAmI();
    std::shared_ptr<Base> copy_of_a_copy = Factory<Base>::clone(copy_of_a);
    copy_of_a_copy->whoAmI();
    return 0;
}

秘訣は、オリジナルがメソッドでどのように構築されたかを覚えておくことですFactory::create(オブジェクトへのポインターを、コピーコンストラクターを呼び出すラムダに関連付けることによって)。古い設計図を捨てないでください。後で必要になる場合があります;-)

率直に言って、私はまだcloneCRTPなどの古いソリューションを好みますが、これはいくつかの新しいアイデアを引き起こすか、そうでなければ便利になるかもしれません。

上記のコードはhttp://ideone.com/kIPFt2にもあります

編集: wjlがコメントしたように、コードの最初のバージョンはcloneFnMap着実に成長するでしょう。よく考えた後、shared_ptr返されるsにカスタム削除機能を導入してコードを修正し、cloneFnMapもクリーンアップされるようにすることにしました。それでも、これは実験的な概念実証コードと見なす必要があります。

于 2015-02-21T15:01:58.553 に答える