Re: Cloning members of a hierarchy
And thus spake Paul N <gw7rib@aol.com>
Mon, 1 Feb 2010 11:45:00 -0800 (PST):
I've got various classes derived (directly or indirectly) from a
single base, and want a function to make a copy of a given object. My
code is along the following lines:
class Base {
public:
int b;
virtual Base *clone() = 0;
};
class Derived : public Base {
public:
int d;
Base *clone() { return new Derived(*this); }
};
Am I right in thinking that I need to include a definition of the
"clone" function for every class that I want to be able to clone
objects of? And that this would be true even if I didn't make it a
pure virtual function? And that there is no easy way round this, short
of using macros to "tidy" the code up?
You can use a template. Without having it run through a compiler, something like this could/should work:
class Base
{
public:
virtual Base* clone() = 0;
};
template <typename T>
class ClonableBase : public Base
{
public:
virtual Base* clone()
{
return new T(*this);
}
}
class Derived: public ClonableBase<Derived>
{
....
};
This should work since every derived class inherits its own implementation of clone() from a template-generated 'buffer' class. However, I do not see much to be gained by this. Just implement the virtual constructors in the derived classes, that way at least the semantics become immediately clear.
But conversely, am I right in
thinking that the automatically-generated copy constructors will do
the actual donkey work of making a copy of all the members at all the
levels for me?
This works if your class looks more or less like a traditional C struct (i.e. a POD type, or 'plain old data'). However, be very, very careful if the constructor performs resource aquisition (and the destructor therefore frees resources). Then it will most probably NOT work, and can even lead to double-deletes and such pains.
As a rule, if your class contains at least one of the following, it will most probably need all three: destructor, copy constructor, assignment operator. In general do no depend on the generated versions, except in very simple cases; they have a tendency to not do what you want or need.
(I was also going to include a question about a potential bug in VC++,
in which it complained about not being able to instatiate an abstract
class - but it turned out that the problem was that one declaration
was declared "const" and the other wasn't, so it was my fault.)
Yes. C++ currently lacks an 'override' keyword (C++ 0x will get it, though), so you cannot tell the compiler that a function is supposed to override a function in the base class. This means that the compiler cannot give a meaningful error message, since it would have to 'guess' what yo actually want to achieve. That said, the Microsoft compiler _does_ support an override modifier as an extension. However, using non-standard extensions lead to non-portable code.
Robert