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