开发者

Making a copy of an object of abstract base class

开发者 https://www.devze.com 2023-02-05 16:35 出处:网络
If I have a pointer to an object that derives from an abstract base class (so I cannot create an new object of that class), and I wish to make a deep copy of said object开发者_Go百科, is there a more

If I have a pointer to an object that derives from an abstract base class (so I cannot create an new object of that class), and I wish to make a deep copy of said object开发者_Go百科, is there a more concise way of accomplishing that than to have the abstract base class create a new pure virtual copy function that every inheriting class has to implement?


No, but the copy method does not have to be painful:

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

(assuming you already have a copy constructor, which, if you need a deep copy, you'll have).


The suggested 'copy', more usually called 'clone' is the normal approach. An alternative would be a factory and dispatch using rtti to find the right handler to then call the copy constructor on the derived type.

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();
}

Whilst the above works, the sheer fact it uses rtti would be enough to persuade most to go the normal approach. However, it there was a reason preventing changes to the base class, it might be useful.

It this efficient? The marginal cost of adding a new type is truly a one-liner. The catch is that it will be easy to forget to add that line with each new class. Or you can see it as an upside that all the clone code lives in a single file and we don't have to change the supported hierarchy to handle it.


A while back someone in comp.lang.c++ asked how to automatically create a clone() function. Someone else provided an idea upon which I expanded. None of it is tested code and I've never actually tried it...but I think it works: http://groups.google.com/group/comp.lang.c++/browse_thread/thread/c01181365d327b2f/9c99f46a8a64242e?hl=en&ie=UTF-8&oe=utf-8&q=comp.lang.c%2B%2B+noah+roberts+clone&pli=1

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号