Home > Blockchain >  Copy an abstract class without modifying it
Copy an abstract class without modifying it

Time:11-05

I have an access to an external library that provides a function that returns a pointer to an abstract class Foo, I want to copy that class but the library is pre-compiled so I cannot add any new functions like the virtual clone function https://en.wikibooks.org/wiki/More_C++_Idioms/Virtual_Constructor.

Is there any other way to copy the contents of the pointer?

class Foo // private precompiled class I cannot add methods to 
{
    virtual void F() = 0;
};
class FooChild : public Foo
{
    void F() override
    {
        
    }
};
static Foo* getFoo()
{
    return new FooChild();
};


int main()
{
    
    Foo* f = getFoo();
    Foo* fCopy = new Foo(f); //cannot do that
    return 0;
}

CodePudding user response:

Your only option is a long if else if chain, based on typeid(*f), with a branch for every possible type.

Foo *copy = nullptr;
if (typeid(*f) == typeid(FooChild))
    copy = new FooChild(static_cast<FooChild &>(*f));
else if // ... same for every child class

CodePudding user response:

If you're not forced to use Foo in your main() there's a way to make this work if you use a FooBase subclass instead.

class Foo
{
public:
    virtual ~Foo() = default;
    virtual void f() = 0;
};

class FooBase: public Foo
{
public:
    virtual FooBase* clone() = 0;
};

template <class Derived>
class FooBase_: public FooBase {
public:
    FooBase* clone() override { return new Derived(static_cast<Derived&>(*this)); }
};

class FooChild1: public FooBase_<FooChild1> {
public:
    FooChild1() = default;
    FooChild1(const FooChild1&) = default;
    void f() override { std::cout << "FooChild1\n"; }
};

class FooChild2: public FooBase_<FooChild2> {
public:
    FooChild2() = default;
    FooChild2(const FooChild2&) = default;
    void f() override { std::cout << "FooChild2\n"; }
};


int main()
{
    
    FooBase* f1 = new FooChild1;
    FooBase* f1Copy = f1->clone();
    f1->f();
    f1Copy->f();

    FooBase* f2 = new FooChild2;
    f2->f();

    delete f1;
    delete f1Copy;
    delete f2;

    return 0;
}

FooBase_ is a CRTP generating a specific clone() method for each FooChildN concrete class, avoiding repetition.

Demo here: https://godbolt.org/z/nva75Gx4x

  •  Tags:  
  • c
  • Related