| re: Duplicating objects with a common base class
Derek wrote:[color=blue]
>
> Pete Nudd wrote:[/color]
[snip][color=blue]
>
> You could use a template to supply a clone() function.
> (I think -- you might want a second opinion because I'm
> making this up as I go along.) Say your base is:
>
> class Base
> {
> public:
> virtual Base* clone() const = 0;
> virtual ~Base() {}
> };
>
> Create a template that defines clone() for any type T
> and is itself derived from Base:
>
> template<class T>
> class CloneableBase : public Base
> {
> public:
> Base* clone() const
> {
> return new T(dynamic_cast<const T&>(*this));
> }
> };
>
> Now inherit from Cloneable instead of using Base
> directly:
>
> class Foo : public CloneableBase<Foo> {};
> class Bar : public CloneableBase<Bar> {};
>
> And you can write:
>
> Base* pb1 = new Foo;
> Base* pb2 = pb1->clone();[/color]
Nitpicking: I'd disagree with the use of dynamic_cast here (other than
for debugging). If CloneableBase<T> is used as intended:
class Bar : public CloneableBase<Bar> {};
then the result of dynamic_cast is equivalent to static_cast.
The only time its observed behaviour will differ from that of static_cast
is when someone grossly misuses CloneableBase<T>, e.g.
class Bar : public CloneableBase<Foo> {};
This, however, should be detected at compile time and, at any rate, never
happen in the production code, so static_cast will do. If this still
didn't sound safe enough, I'd just revert to the original scheme.
(FWIW, I use dynamic_cast only when I really have to (i.e. when downcasting
can only be resolved at run-time and must be controlled for safety, and
there are no design alternatives). The former use is a domain serviced
well enough by virtual functions alone. On a practical note, at least
some popular implementations of dynamic_cast are very inefficient).
Denis |