Re: Virtual constructor?
ThosRTanner wrote:
Gene Bushuyev wrote:
"Azumanga" <4zumanga@gmail.com> wrote in message
news:1149031273.468412.11660@v35g2000cwv.googlegroups.com...
Imagine I have the following code:
struct A { .. };
struct B : public A { .. };
struct C : public A { .. };
[...]
A* copy_object(A* obj)
{
if(B* b_obj = dynamic_cast<B*>(obj))
{ return new B(*b_obj); }
This code is an absolute anathema to object-oriented
programming. Each code that relies on switching on types is
not only error-prone, it breaks the foundational open-close
design principle. Your function must know about every
possible derivative of A, changing every time whenever the
classes are changed or new classes added.
or:
struct A
{ virtual A* clone() { return new A(*this);} ... };
struct B : public A
{ virtual B* clone() { return new B(*this);} ... };
This is a typical way of cloning objects (except it should
be const,) which is sometimes called "virtual constructor."
There is nothing error-prone about it, the only
inconvenience is typing virtually the same code in every
class.
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.
Personally, I'm not sure its worth it for just the one function;
if several functions are involved, or the function is more
complex, however, it is certainly worth considering.
Another frequent variation is to implement verifications in the
base class, i.e.:
class Base
{
public:
/* NOT virtual */ Base* clone() const
{
Base* result = doClone() ;
assert( typeid( *result ) == typeid( *this ) ) ;
return result ;
}
private:
virtual Base* doClone() const = 0 ;
} ;
This way, if anyone forgets to override doClone, you find out
about it immediately. (If doClone is pure virtual, an
immediately derived class cannot forget. But if the hierarchy
has a certain depth, it could conceivably happen.)
--
James Kanze GABI Software
Conseils en informatique orient?e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S?mard, 78210 St.-Cyr-l'?cole, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]