-
Clone function
Hi everyone!
I canīt seem to figure out how to do correctly a clone function to an object. I searched through the board, but found nothing.
One wrong way woule be:
Code:
const X& clone(){
return X(/*attributes*/);
}
But at the end of the clone function, the object is destroyied, deallocating any other object inside of it.
Other way:
Code:
const X& clone(){
X* temp = new X(/*attributes*/);
return *temp;
}
But then, the object isnīt deallocated...
How can I do it?
Thanks any help!
-
Well, maybe there's something special about a "clone" function that I havn't heard of, but if you want to be able to copy an instance of a class then I suggest searching the board & google for overload assignment operator and copy constructor. If you want a function to generate a "clone" you could use the dynamic memory allocation and then in your documentation state that the client needs to delete the object when done. OR create an instance of the object, pass it to the clone function to be cloned with all the values of the instance of the class being cloned.
-
If you want to use the clone function polymorphically then make it return a pointer and dynamically allocate a copy from within the function. Yes, this does mean that the user is responsible for deallocating the object. Then, using covariant return types, your function will return a pointer to the child type when called from a pointer to the child and will return a pointer to the base when called from the base:
Code:
class base
{
public:
virtual base* clone() const
{
return new base;
}
virtual ~base() {}
};
class child
: public base
{
public:
child* clone() const
{
return new child;
}
};
int main()
{
base base_inst;
child child_inst;
base& child_ptr = child_inst;
child* Test0 = child_inst.clone(), // works
* Test1 = base_inst.clone(), // doesn't work
* Test2 = child_ptr.clone(); // doesn't work
delete Test0;
delete Test1;
delete Test2;
}
Also, as a side note, MSVC++ .NET 2003 does NOT support co-variant return types when you are dealing with virtual base classes.
-
Thank you both. But, I do not want to pass the object that will receive the clone because is not "clean". I do not want to use a pointer, because I already know. For better explanation, I copied the prototype of the copy function of the string class:
Code:
string copy() const throw( xalloc )
Notice that it returns an object, so, probaly, at the end of the function there is something like:
Code:
return string("old string");
But, trying to make an example to show what I meant I discovered what was my error:
I was returning a const reference before:
Code:
const X& clone(){ return X(); }
For some reason, the destructor of the object created on return is called before any attribution.
But now:
Code:
X clone(){ return X(); }
Works fine...
*sigh* I do not know why this happens :-(
Anyway, thanks again.
-
To understand what is happening, look at this example:
Code:
class X
{
int i_;
public:
X(int i) : i_(i) { }
};
const X& clone1() { return X(1); }
X clone2() { return X(2); }
int main()
{
X x1 = clone1();
X x2 = clone2();
}
For x1, clone1 is returning a reference to the temporary variable created inside its return statement. As soon as that return statement completes, the temporary variable goes out of scope and is destroyed, so your x1 variable is referencing a destroyed object.
On the other hand, clone2 returns a new object that is a copy of the temporary variable created inside the return statement. This copy is made using the copy constructor (either the default copy constructor or one you add to the class). Since x2 is only a copy of and not a reference to the temporary variable, it is still valid after the temporary is destroyed.
I do wonder whether you want clone() to be called only in certain situations where you know the source is not "clean", or you never want the copy constructor or operator= to be called. If it is the second case, I'm not sure why, since you can just make the copy constructor and operator= do the same thing as clone() is doing. I ask because your version of clone might be doing things you don't want it to do with the implicit call to the copy constructor and/or operator=.
-
Quite simply, one returns a reference to a variable. However, the variable to which it is pointing (b/c a reference is similar to a pointer) is destroyed. The other is returning an object itself, not a reference. Hence, the object is not destroyed b/c it is the one actually being returned.
-
jlou, the clone function was an exercise from a book. The "clean" is just about passing the object that will receive the clone as a parameter.
golfinguy4, I read that the return object() is, actually a syntax. The compiler, seeing that return wll call the copy constructor of the lvalue.
Thanks you both!