Virtual constructor
1234567891011121314151617181920212223 | #include <memory>
class Base
{
public:
virtual ~Base() {}
virtual Base* clone() const = 0;
};
class Derived : public Base
{
public:
Derived* clone() const override
{
return new Derived(*this);
}
};
void foo(std::unique_ptr<Base> original)
{
std::unique_ptr<Base> copy{original->clone()};
} |
This pattern is licensed under the CC0 Public Domain Dedication.
Intent
Create a copy of an object through a pointer to its base type.
Description
You can’t copy an object unless you know its static type, because the compiler must know the amount of space it needs to allocate. Therefore we can’t copy an object of derived type directly through a pointer to its base.
The virtual constructor idiom is a technique for delegating the
act of copying the object to the derived class through the use of
virtual functions. To demonstrate, we declare a virtual member
function of Base
on line 8 (typically named clone
) that each of
the derived classes will implement to return a copy of themselves.
The Derived
class implements this clone
function on lines 14–17,
simply by creating a copy of itself and returning it.
Now, consider that we are given a std::unique_ptr<Base>
on line 20
pointing to an object of derived type that we wish to copy (this
could alternatively be a Base*
or any other smart pointer to
Base
). To perform this copy, we simply call the virtual clone
member function through the pointer on line 22, which thanks to
polymorphism calls the Derived
implementation of clone
,
returning a pointer that points to a copy of the original derived
object.
Note: It is not possible to implement the virtual constructor
idiom as-is with smart pointers, as derived virtual member
functions must have covariant return types. One workaround
is for Derived::clone
to return a Base
pointer instead.
Alternatively, you can provide non-virtual wrapper
functions.