Re: Virtual constructor?
kanze wrote:
ThosRTanner wrote:
[...]
Isn't this one of those places where you use the Curiously
Recurring Template pattern
template <class C> cloneable { virtual C* clone() return new C(*this) }
and then do
struct B : public A, cloneable<B> { .... }
One can, although it would more likely be something like:
template< typename Derived, typename Base >
class Clonable : public base
{
virtual Base* clone() const
{
return new Derived( *dynamic_cast< Derived const* >( this )
) ;
}
} ;
class B : public Clonable< B, A > ...
Otherwise, the function clone in the template won't override the
function clone in the base class.
Why dynamic_cast when static_cast is sufficient? You can't use this
for virtual inheritance anyway:
class B{ ... };
class B1: virtual public Clonable<B1,B> { ... };
class B2: virtual public Clonable<B2,B> { ... };
class D: public Clonable2<D,B1, B2> { ... };
// D contains _two_ subobjects of class B
You'd need to add some traits to the template parameters for Clonable
to indicate the type of inheritance (public/private/protected,
normal/virtual). And, of course, to ClonableX for multiple inheritance.
The other problem is the return type of the clone function. Ideally it
should be Derived*, but this is not possible. There's been a thread in
clc++m in late 2004 where I suggested the following:
// WARNING: THIS DOES NOT WORK
template <class Derived,class Base>
struct Clonable: Base {
virtual Derived* clone() const{
return new Derived(static_cast<const Derived&>(*this));
}
};
struct B { virtual B* clone() const =0; virtual ~B(); };
struct D: Clonable<D,B> { };
The idea is that the Clonable<D,B>::clone's result type would be D*
which is covariant with B*. A few months later someone asked about
this again and I discovered that it can't work. The problem is that
during the _instantiation_ of the _declaration_ of Clonable<D,B>::clone
D is still an incomplete type and the base-derived relation between D
and B doesn't exist yet.
In the end it seems that writing the clone function manually is the
best option.
Cheers
Vladimir
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]