5

抽象基本クラスから派生したオブジェクトへのポインターがあり (そのため、そのクラスの新しいオブジェクトを作成できません)、そのオブジェクトのディープ コピーを作成したい場合、それを達成するためのより簡潔な方法はありますか?抽象基本クラスcopyに、すべての継承クラスを実装する必要がある新しい純粋仮想関数を作成させるには?

4

3 に答える 3

10

いいえ、しかしcopy方法は苦痛である必要はありません:

class Derived : public Base
{
  public:
    Base *copy() const
    {
        return new Derived(*this);
    }
};

(すでにコピー コンストラクターがあると仮定します。ディープ コピーが必要な場合は、コピー コンストラクターが必要です)。

于 2011-01-21T03:38:47.413 に答える
1

提案された「コピー」、通常は「クローン」と呼ばれる方法が通常のアプローチです。代替手段は、ファクトリとディスパッチを使用して rtti を使用し、適切なハンドラーを見つけてから、派生型でコピー コンストラクターを呼び出すことです。

struct Abc
{
    virtual void who() const = 0;
};

struct A : Abc
{
    virtual void who() const { std::cout << "A" << std::endl;}
};

template<class T>
Abc* clone(Abc* abc)
{
    T* t = dynamic_cast<T*>(abc);
    if (t == 0)
        return 0;
    return new T(*t);
}

struct B : Abc
{
    virtual void who() const { std::cout << "B" << std::endl;}
};

typedef Abc* (*Cloner)(Abc*);

std::map<std::string, Cloner> clones;

void defineClones()
{
    clones[ typeid (A).name() ] = &clone<A>;
    clones[ typeid (B).name() ] = &clone<B>;
}


Abc* clone(Abc* abc)
{
    Abc* ret = 0;
    const char* typeName  = typeid(*abc).name();
    if (clones.find(typeName) != clones.end())
    {
        Cloner cloner = clones[typeName];
        ret = (*cloner)(abc);
    }
    return ret;
}
void test ()
{
    defineClones();
    Abc* a = new A;
    Abc* anotherA = clone(a);
    anotherA->who();

    Abc* b = new B;
    Abc* anotherB = clone(b);
    anotherB->who();
}

上記は機能しますが、rtti を使用しているという事実だけで、ほとんどの人が通常のアプローチに進むよう説得するのに十分です。ただし、基本クラスへの変更を妨げる理由があった場合は、役立つ可能性があります。

こんなに効率的?新しいタイプを追加する限界費用は、まさにワンライナーです。問題は、新しいクラスごとにその行を追加するのを忘れやすいことです。または、すべてのクローン コードが 1 つのファイルに存在し、それを処理するためにサポートされている階層を変更する必要がないという利点もあります。

于 2011-01-21T03:39:53.027 に答える
1

しばらく前に、comp.lang.c++ の誰かが clone() 関数を自動的に作成する方法を尋ねました。他の誰かが私が拡張したアイデアを提供しました。どれもテストされたコードではなく、実際に試したことはありません...しかし、うまくいくと思います : =en&ie=UTF-8&oe=utf-8&q=comp.lang.c%2B%2B+noah+roberts+clone&pli=1

于 2011-01-21T04:28:20.850 に答える