Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Automatically create a clone() function for derived classes

317 views
Skip to first unread message

Juha Nieminen

unread,
Feb 20, 2009, 9:25:21 AM2/20/09
to
I'm sure this is a frequently asked question, but...

Suppose that I have a hierarchy of objects which are typically
allocated dynamically and handled with some smart pointer or whatever.
However, I want to be able to create copies of those objects, while
having only a pointer-to-base-class. The solution is to write a clone()
member function like this:

class Base
{
public:
virtual Base* clone() const { return new Base(*this); }

// other stuff here
};

The problem is that this clone() function must be replicated in all
the derived classes as well, and their implementation is always the
same, except for the type which is being allocated. For example:

class Derived: public Base
{
public:
virtual Base* clone() const { return new Derived(*this); }
};

It's not only tedious to have to write this line in each of the
derived classes, but it's also error-prone: If you ever forget to add
that line to some derived class, no compiler error will happen, and the
program will even run, but when cloning a derived object using a base
type pointer, you get a crippled copy, so the whole thing malfunctions,
and it might malfunction in a very non-obvious way which is hard to
track and debug.

Isn't there any way of automating this process? (And without making
the base class a template class, which would be rather tedious if the
base class is large, especially since we don't have export templates in
practice.)

Sana

unread,
Feb 20, 2009, 9:47:44 AM2/20/09
to
On Feb 20, 9:25 am, Juha Nieminen <nos...@thanks.invalid> wrote:
>
> class Base
> {
>  public:
>     virtual Base* clone() const { return new Base(*this); }
>
>     // other stuff here
>
> };
>
>   The problem is that this clone() function must be replicated in all
> the derived classes as well, and their implementation is always the
> same, except for the type which is being allocated. For example:
>
> class Derived: public Base
> {
>  public:
>     virtual Base* clone() const { return new Derived(*this); }
>
> };
>
>   It's not only tedious to have to write this line in each of the
> derived classes, but it's also error-prone: If you ever forget to add
> that line to some derived class, no compiler error will happen, and the
> program will even run, but when cloning a derived object using a base
> type pointer, you get a crippled copy, so the whole thing malfunctions,
> and it might malfunction in a very non-obvious way which is hard to
> track and debug.
>

Make the Base::clone() method pure and don't provide a body. this way,
if the derived class doesn't implement the clone() method, the linker
will complain.

virtual Base* clone() const = 0;

--
sana

Victor Bazarov

unread,
Feb 20, 2009, 10:09:50 AM2/20/09
to

Then the problem would be with a derived class of a derived class (a
"grandchild" of Base). Once the derived has implemented the clone
function, any of its own derived classes won't be forced to do that.

And that's actually reflected in the original inquiry since Base::clone
is *not* pure. IOW there is no simple way to force (or provide) the
implementation of such a "clone" function in the derived class *in case*
the base class' member is not pure.

In certain circles, a macro is used

class Derived : public Base {
DECLARE_BASE(Base);
DECLARE_CLONABLE(Derived);

which expands to declare the 'clone' member (with some possible
compile-time checks etc.) It's a bit better than declaring/defining the
whole separate member, but the programmer still needs to use it in order
to accomplish the goal at hand.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask

Thomas J. Gritzan

unread,
Feb 20, 2009, 12:03:36 PM2/20/09
to
Juha Nieminen schrieb:

> I'm sure this is a frequently asked question, but...

It is (but it's not in the FAQ)!

> Suppose that I have a hierarchy of objects which are typically
> allocated dynamically and handled with some smart pointer or whatever.
> However, I want to be able to create copies of those objects, while
> having only a pointer-to-base-class. The solution is to write a clone()
> member function like this:
>
> class Base
> {
> public:
> virtual Base* clone() const { return new Base(*this); }
>
> // other stuff here
> };
>
> The problem is that this clone() function must be replicated in all
> the derived classes as well, and their implementation is always the
> same, except for the type which is being allocated. For example:

[...]

1) You can use CRTP to avoid writing all the code again and again.
2) You can try some programming by contract to check if someone forgot
to implement its clone().

Both is described in this posting (the complete thread might be of
interest, too):
http://groups.google.de/group/comp.lang.c++.moderated/msg/993079dca61f3a20?hl=de

--
Thomas

blargg

unread,
Feb 22, 2009, 4:10:14 PM2/22/09
to
In article <l3znl.97$zj6...@read4.inet.fi>, Juha Nieminen
<nos...@thanks.invalid> wrote:
[...]

> class Base
> {
> public:
> virtual Base* clone() const { return new Base(*this); }
>
> // other stuff here
> };
>
> The problem is that this clone() function must be replicated in all
> the derived classes as well, and their implementation is always the
> same, except for the type which is being allocated. For example:
>
> class Derived: public Base
> {
> public:
> virtual Base* clone() const { return new Derived(*this); }
> };
>
> It's not only tedious to have to write this line in each of the
> derived classes, but it's also error-prone: If you ever forget to add
> that line to some derived class, no compiler error will happen, and the
> program will even run, but when cloning a derived object using a base
> type pointer, you get a crippled copy, so the whole thing malfunctions,
> and it might malfunction in a very non-obvious way which is hard to
> track and debug.
>
> Isn't there any way of automating this process?
[...]

Odd-ball approach that comes to mind, if compile-time checking is
insisted on:

class Clonable {
protected:
template<class T>
Clonable( T const* t )
{
// ensure that T implements covariant clone
if ( false )
t = t->clone();
}

// OK to remove this
virtual Clonable* clone() const = 0;
};

class Base : protected virtual Clonable {
public:
Base() : Clonable( this ) { }


Base* clone() const { return new Base( *this ); }

};



class Derived : public Base {
public:

Derived() : Clonable( this ) { }
Derived* clone() const { return new Derived( *this ); }
};

class Error : public Derived {
public:
// error, Clonable doesn't have default ctor
Error() /* : Clonable() */ { }
};

class Error2 : public Derived {
public:
// error, clone() doesn't return Error2*
Error2() : Clonable( this ) { }
};

You could probably use a similar approach, with Clonable generating the
clone function automatically, and the derived class just needing to pass
'this' to Clonable so that its template will be instantiated for the
derived type.

Noah Roberts

unread,
Feb 23, 2009, 12:39:25 PM2/23/09
to

Calling virtual function from within constructor == very bad. Besides
that it looks like a rather interesting solution. I think you could
improve it through something similar to boost::any:

class Clonable {
protected:

template < typename T >
Clonable( T const* t) : pimpl(new impl<T>(t))
{}
Clonable * clone() const { return pimpl->clone(); }

private:
struct impl_base
{


virtual Clonable* clone() const = 0;
};

template < typename T >
struct impl : impl_base
{
impl(T const* t) : var(t) {}
Clonable * clone() const { return new T(var); }
T const* var;
};

scoped_ptr<impl_base> pimpl;
};

Leave your virtual inheritance and turn Base::clone into:

Base * Base::clone() const { return static_cast<Base*>(Clonable::clone()); }

Wouldn't even need to be virtual as the polymorphism is taken care of by
Clonable's pimpl.

This is untested but I'm pretty confident it, or something like it,
would work. The only thing lost is the ability to construct Derived
pointers without casts even when you know the Derived type. Some sort
of policy based programming might do the trick there.

Victor Bazarov

unread,
Feb 23, 2009, 12:47:46 PM2/23/09
to
Noah Roberts wrote:
> blargg wrote:
>> [..]

>> Odd-ball approach that comes to mind, if compile-time checking is
>> insisted on:
>>
>> class Clonable {
>> protected:
>> template<class T>
>> Clonable( T const* t )
>> {
>> // ensure that T implements covariant clone
>> if ( false )
>> t = t->clone();
>
> Calling virtual function from within constructor == very bad.[..]

It's not really calling it if it's behind the 'if (false)', is it?

blargg

unread,
Feb 23, 2009, 6:03:13 PM2/23/09
to
Noah Roberts wrote:
> blargg wrote:
[...]
> > Odd-ball approach that comes to mind, if compile-time checking is
> > insisted on:
> >
> > class Clonable {
> > protected:
> > template<class T>
> > Clonable( T const* t )
> > {
> > // ensure that T implements covariant clone
> > if ( false )
> > t = t->clone();
>
> Calling virtual function from within constructor == very bad. Besides
> that it looks like a rather interesting solution.

Controlled by an if statement whose condition is never true == perfectly
OK. The purpose is to ensure that T's clone function returns a T* (or
something derived from it). This way, if T forgets to define clone, the
base class version would be found and its return type wouldn't be
implicitly convertible to T*.

> I think you could improve it through something similar to boost::any:
>
> class Clonable {
> protected:
>
> template < typename T >
> Clonable( T const* t) : pimpl(new impl<T>(t))
> {}
> Clonable * clone() const { return pimpl->clone(); }
>
> private:
> struct impl_base
> {
> virtual Clonable* clone() const = 0;
> };
> template < typename T >
> struct impl : impl_base
> {
> impl(T const* t) : var(t) {}
> Clonable * clone() const { return new T(var); }
> T const* var;
> };
>
> scoped_ptr<impl_base> pimpl;
> };
>
> Leave your virtual inheritance and turn Base::clone into:
>
> Base * Base::clone() const { return static_cast<Base*>(Clonable::clone()); }
>
> Wouldn't even need to be virtual as the polymorphism is taken care of by
> Clonable's pimpl.

The virtual inheritance is necessary to force the most-derived class to
call the Clonable constructor with the 'this' pointer, to indirectly
pass its type. BTW, you don't need any type of embedded object at all,
just a function pointer:

class Clonable {
template<class T>
static Clonable* clone_t( Clonable const* c ) {
return new T( static_cast<T const*> (c) );
}
Clonable* (*clone_)( Clonable* );
protected:
template<class T>
Clonable( T* ) : clone_( &clone_t<T> ) { }

public:
Clonable* clone() const { return clone_( this ); }
};

class Base : public virtual Clonable {


public:
Base() : Clonable( this ) { }

Base* clone() const {


return static_cast<Base*> (Clonable::clone());
}

};



class Derived : public Base {
public:

Derived() : Clonable( this ) { }

// if you forget this, user is merely inconvenienced, rather
// than given Base slice of the object
Derived* clone() const {
return static_cast<Derived*> (Clonable::clone());
}
};

> This is untested but I'm pretty confident it, or something like it,
> would work. The only thing lost is the ability to construct Derived
> pointers without casts even when you know the Derived type. Some sort
> of policy based programming might do the trick there.

Or just forwarding functions as you mentioned. Of course I think the cost
of ensuring correct clone() implementation greatly outweights the benefit,
as compared to using external tests to ensure each class implements a
clone in the straight-forward way:

Foo* clone() const { return new Foo( *this ); }

thari...@gmail.com

unread,
Feb 24, 2009, 7:18:40 AM2/24/09
to
> but it's also error-prone: If you ever forget to add
> that line to some derived class, no compiler error will happen, and the
> program will even run, but when cloning a derived object using a base
> type pointer, you get a crippled copy, so the whole thing malfunctions,
> and it might malfunction in a very non-obvious way which is hard to
> track and debug.
>

Hi,

I'm not a c++ expert but can't we tackle this problem by having co-
variant virtual functions at the derived classes ?

so it would be like

class Base
{
public:
virtual Base* clone() const { return new Base(*this); }

// other stuff here

};

AND

class Derived: public Base
{
public:

virtual Derived* clone() const { return new Derived(*this); } //
return type is different

};

when you clone an object of the type "Derived" and try to assign it to
a pointer to the type "Derived" it will fail at compile time if there
is no such co-variant implementation in the derived type.

Of course you can use macros to do it like this

#define DECLARE_CLONE(class_name) \
virtual class_name* Clone();

#define IMPLEMENT_CLONE(class_name) \
class_name* class_name::Clone() \
{ return new class_name(*this); }


REH

unread,
Feb 24, 2009, 12:08:09 PM2/24/09
to
On Feb 24, 7:18 am, tharinda...@gmail.com wrote:
> when you clone an object of the type "Derived" and try to assign it to
> a pointer to the type "Derived" it will fail at compile time if there
> is no such co-variant implementation in the derived type.
>

If that were the case, he could simple use a copy constructor. The
problem is he only has a pointer to the base class, and doesn't know
the actual type. Thus, the need for a polymorphic member function to
do the work for him.

REH

blargg

unread,
Feb 24, 2009, 6:53:04 PM2/24/09
to
blargg wrote:
> Noah Roberts wrote:
[...]

> > This is untested but I'm pretty confident it, or something like it,
> > would work. The only thing lost is the ability to construct Derived
> > pointers without casts even when you know the Derived type. Some sort
> > of policy based programming might do the trick there.
>
> Or just forwarding functions as you mentioned. Of course I think the cost
> of ensuring correct clone() implementation greatly outweights the benefit,
> as compared to using external tests to ensure each class implements a
> clone in the straight-forward way:
>
> Foo* clone() const { return new Foo( *this ); }

And if you don't need covariance, you can use
the non-virtual interface approach to get
automatic checking at run-time:

class Base {
virtual Base* clone_() const { return new Base( *this ); }

public:
Base* clone() const // non-virtual
{
Base* b = clone_();
assert( typeid(*b) == typeid(*this) );
return b;
}
};


class Derived : public Base {
virtual Base* clone_() const { return new Derived( *this ); }
};

class Error : public Derived {
// forgot to define clone_
};

int main()
{
(new Derived)->clone(); // OK
(new Error )->clone(); // assertion failure
}

blargg

unread,
Feb 25, 2009, 2:02:58 AM2/25/09
to
REH wrote:

tharinda's point above is that the error of forgetting to define the
derived clone() will be caught when an attempt is made to call clone() on
a Derived* and assign the result to a Derived*. Catching this error is the
whole point of this thread.

But even with covariant overrides of clone(), if someone clones a Derived
object given just a Base*, a forgotten override of clone() in Derived
won't be caught.

thari...@gmail.com

unread,
Feb 25, 2009, 2:14:31 AM2/25/09
to
On Feb 25, 12:02 pm, blargg....@gishpuppy.com (blargg) wrote:


> But even with covariant overrides of clone(), if someone clones a Derived
> object given just a Base*, a forgotten override of clone() in Derived
> won't be caught.

that problem would be solved if you use a macro to declare and define
the class methods :)

Thanks!

Tharinda

blargg

unread,
Feb 25, 2009, 3:53:31 AM2/25/09
to
tharinda wrote:

> blargg wrote:
> > But even with covariant overrides of clone(), if someone clones a Derived
> > object given just a Base*, a forgotten override of clone() in Derived
> > won't be caught.
>
> that problem would be solved if you use a macro to declare and define
> the class methods :)

How does defining such a macro prevent one from forgetting to invoke it?

thari...@gmail.com

unread,
Feb 25, 2009, 4:15:03 AM2/25/09
to

I mean if somebody is strictly adhered to a rule so that the clone
function is implemented only by a macro like this

#define DECLARE_CLONE(class_name) \
virtual class_name* Clone();

#define IMPLEMENT_CLONE(class_name) \
class_name* class_name::Clone() \
{ return new class_name(*this); }

then there is no way you can accidentally change the return type of
the derived function.

Thanks!

Tharinda

blargg

unread,
Feb 25, 2009, 5:29:26 AM2/25/09
to
tharinda.gl wrote:

> On Feb 25, 1:53=A0pm, blargg....@gishpuppy.com (blargg) wrote:
> > tharinda wrote:
> > > blargg wrote:
> > > > But even with covariant overrides of clone(), if someone clones a Der=

> ived
> > > > object given just a Base*, a forgotten override of clone() in Derived
> > > > won't be caught.
> >
> > > that problem would be solved if you use a macro to declare and define
> > > the class methods :)
> >
> > How does defining such a macro prevent one from forgetting to invoke it?
>
> I mean if somebody is strictly adhered to a rule so that the clone
> function is implemented only by a macro like this
>
> #define DECLARE_CLONE(class_name) \
> virtual class_name* Clone();
>
> #define IMPLEMENT_CLONE(class_name) \
> class_name* class_name::Clone() \
> { return new class_name(*this); }
>
> then there is no way you can accidentally change the return type of
> the derived function.

I think you missed the main point; I'll recap since I'm not sure where
we diverge. The original poster wanted to use a virtual clone() in the
base class, but wanted a way to catch the error of forgetting to
override it in derived classes, even multiple levels deep (where making
the base function pure wouldn't help). He wanted a compile-time error,
but I've generalized that to reliably getting SOME kind of error.

You noted that with covariant return types, this error will be caught in
some cases at compile-time:



class Base {
public:
virtual Base* clone() const { return new Base( *this ); }

};



class Derived : public Base {
public:

virtual Derived* clone() const { return new Derived( *this ); }
};

class Error : public Base {
public:
// forgot clone()
};

void user( Base* b, Derived* d, Error* e )
{
d = d->clone(); // OK
e = e->clone(); // error, since e.clone() returns a Base*

b = b->clone(); // OK, even if b points to an Error object
}

If an error object were only ever cloned via a Base*, the error would
never be reliably caught. Thus, using covariant returns isn't sufficient
to reliably catch the error of a forgotten clone() override. Using a
macro to automate the declaration/definition of derived clone() doesn't
do anything to prevent the derived class author from forgetting to
invoke it. My point about using a Base* in the quoted message wasn't
about the derived class author overriding clone() wrong; it was about
him not overriding it at all, and users cloning entirely through Base*.

Sorry for the verbosity.

thari...@gmail.com

unread,
Feb 25, 2009, 6:53:27 AM2/25/09
to

blargg, Yes you are correct, my solution won't be a concrete method of
finding whether the developer has forgotten to implement the clone
method at the derived class. I assumed following things in my
solution.

1. If we don't have the definition of the Derived class then there is
no point of making sure the created object is really a object of the
derived type since we only have access to the base type. This may not
be true for all the cases.

2. If you want to do some kind of down-casting then you have to worry
about the actual data type at that point.

2. If you have the definition of the derived type then you can always
use a pointer to to that type in order to get the cloned object (so
that the compiler error would be generated if there is no such
overridden method).

3. You can make sure the return type always refers to the most derived
type by using some kind of a macro.

As I have mentioned earlier, I am not a c++ pro and still learning
this marvelous language. I really appreciate on the effort that you
people are putting in order improve our knowledge.

Thanks!

Tharinda

Bart van Ingen Schenau

unread,
Feb 25, 2009, 9:24:27 AM2/25/09
to
On Feb 25, 12:53 pm, tharinda...@gmail.com wrote:
>
> blargg, Yes you are correct, my solution won't be a concrete method of
> finding whether the developer has forgotten to implement the clone
> method at the derived class. I assumed following things in my
> solution.
>
> 1. If we don't have the definition of the Derived class then there is
> no point of making sure the created object is really a object of the
> derived type since we only have access to the base type. This may not
> be true for all the cases.

In fact, it is extremely rare that this assumption would be true.
In general, if you have
T* orig;
T* p_new;
//...
p_new = orig->clone();
then most programmers will assume that
orig->do_something();
and
p_new->do_something();
will have exactly the same effect on their respective objects.

It does not matter that you don't know about the additional functions
that a derived class exposes. The expectation is that the virtual
functions that you call (indirecly) through the Base interface resolve
to the same functions.

>
> Thanks!
>
> Tharinda

Bart v Ingen Schenau

blargg

unread,
Feb 25, 2009, 9:16:44 PM2/25/09
to
Bart van Ingen Schenau wrote:

> On Feb 25, 12:53=A0pm, tharinda...@gmail.com wrote:
> > blargg, Yes you are correct, my solution won't be a concrete method of
> > finding whether the developer has forgotten to implement the clone
> > method at the derived class. I assumed following things in my
> > solution.
> >
> > 1. If we don't have the definition of the Derived class then there is
> > no point of making sure the created object is really a object of the
> > derived type since we only have access to the base type. This may not
> > be true for all the cases.
>
> In fact, it is extremely rare that this assumption would be true.
> In general, if you have
> T* orig;
> T* p_new;
> //...
> p_new =3D orig->clone();

> then most programmers will assume that
> orig->do_something();
> and
> p_new->do_something();
> will have exactly the same effect on their respective objects.
>
> It does not matter that you don't know about the additional functions
> that a derived class exposes. The expectation is that the virtual
> functions that you call (indirecly) through the Base interface resolve
> to the same functions.

Besides, if you really didn't mind a Base slice of the object, you
wouldn't even need a clone function:

void user( Base const& b )
{
Base slice( b );
...
}

user( Base() );
user( Derived() );

Noah Roberts

unread,
Feb 26, 2009, 12:03:07 PM2/26/09
to
Noah Roberts wrote:

> class Clonable {
> protected:
>
> template < typename T >
> Clonable( T const* t) : pimpl(new impl<T>(t))
> {}
> Clonable * clone() const { return pimpl->clone(); }
>
> private:
> struct impl_base
> {
> virtual Clonable* clone() const = 0;
> };
> template < typename T >
> struct impl : impl_base
> {
> impl(T const* t) : var(t) {}
> Clonable * clone() const { return new T(var); }
> T const* var;
> };
>
> scoped_ptr<impl_base> pimpl;
> };

Actually, thinking about it more I'm pretty confident that this
interface could be further extended so that the clone functionality
isn't even in the class you're using and you could use ANY inheritance
tree in this manner. This would be the optimal design in many cases.

You would simply implement this as a sort of smart pointer that does
deep-cloning on whatever object it points to. Should be relatively
straightforward to implement using the techniques in the above so I'm
not going to do so here.

What would be really nice is a policy based smart pointer that you could
add this functionality to as a policy. Might look into Loki to see if
it's there already.

James Kanze

unread,
Mar 1, 2009, 7:31:30 PM3/1/09
to

I would imagine some development tools would have a means of
automatically generating the function. Otherwise, blargg and
Noah Roberts have proposed an interesting solution, albeit with
some runtime overhead (an additional dynamic
allocation---probably not significant for the types of things
which usually get cloned). But is the extra code really a
problem? It's not that much. The "classical" solution settles
for a runtime check:

class Base
{
public:
Base* clone() const
{
Base* result = doClone() ;
assert( typeid( *result ) == typeid( *this ) ) ;
return result ;
}

private:
virtual Base* doClone() const = 0 ;
} ;

(Actually, the classical solution doesn't do anything special.
In practice, I've never found forgetting to implement the clone
function in a derived class to be a real problem. All the more
so in that hierarchies which support cloning rarely contain
classes which derive from a concrete type anyway, so making
clone() pure virtual in the base class suffices to ensure a
compiler error.)

--
James Kanze (GABI Software) email:james...@gmail.com
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

0 new messages