Re: Cloning members of a hierarchy
On 1 Feb, 20:17, Robert Fendt <rob...@fendt.net> wrote:
And thus spake Paul N <gw7...@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, somethi=
ng 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>
{
...
};
So far I haven't learnt anyhting about templates, but this is further
evidence that it would be a good idea if I did.
This should work since every derived class inherits its own implementatio=
n of clone() from a template-generated 'buffer' class. However, I do not se=
e 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 th=
e constructor performs resource aquisition (and the destructor therefore fr=
ees resources). Then it will most probably NOT work, and can even lead to d=
ouble-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 oper=
ator. In general do no depend on the generated versions, except in very sim=
ple cases; they have a tendency to not do what you want or need.
Ah. I knew about the "rule of three". But you saying it makes me
realise that my class does in fact have a memory leak, one which I'd
totally overlooked before.
(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, thoug=
h), 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 m=
eaningful error message, since it would have to 'guess' what yo actually wa=
nt to achieve. That said, the Microsoft compiler _does_ support an override=
modifier as an extension. However, using non-standard extensions lead to n=
on-portable code.
Many thanks for your help.
Paul.