views:

2650

answers:

5

When programming C++ we used to create copy constructors when needed (or so we were taught). When switching to Java a few years ago, I noticed that the Cloneable interface is now being used instead. C# followed the same route defining the ICloneable interface. It seems to me that cloning is part of the definition of OOP. But I wonder, why were these interfaces created, and the copy constructor seems to have been dropped?

When I thought about it, I came to the thought that a copy constructor would not be useful if one needs to make a copy of an object whose type is not known (as in having a reference to a base type). This seems logical. But I wonder whether there are other reasons that I do not know of, for which the Cloneable interfaces have been favored over copy constructors?

+3  A: 

It's the issues of final type and of cascading the clone operation through the super classes which is not addressed by copy constructors - they are not extensible. But the Java clone mechanism is widely considered badly broken too; especially problems where a subclass does not implement clone(), but inherits from a superclass that implements cloneable.

I strongly recommend you research cloning carefully, whatever path you choose - you will likely choose the clone() option, but make sure you know exactly how to do it properly. It's rather like equals() and hashCode() - looks simple on the surface, but it has to be done exactly right.

Software Monkey
+4  A: 

Because C++ and Java (and C#) aren't the same thing. C++ has no built-in interfaces because interfaces aren't part of the language. You can fake them with abstract classes but they aren't how you think about C++. Also, in C++ assignment is normally deep.

In Java and C# assignment just involves copying the handle to the internal object. Basically when you see:

SomeClass x = new SomeClass();

in Java or C#, there's a level of indirection builtin that doesn't exist in C++. In C++, you write:

SomeClass* x = new SomeClass();

Assignment in C++ involves the dereferenced value:

*x = *another_x;

In Java you can get access to the "real" object as there is no dereference operator like *x. So to do a deep copy, you need a function: clone(). And both Java and C# wrapped that function into an interface.

jmucchiello
+11  A: 

I think it's because there is no such inherent need for a copy constructor in Java and in C# for reference types. In C++ objects are named. You can (and you will most often) copy (and in C++1x move) them around e.g when returning from functions, since returning pointers require you to allocate dynamic memory which would be slow and painful to manage. The syntax is T(x) so it makes sense to make a constructor taking a T reference. C++ couldn't make a clone function, since that would require returning an object by value again (and thus another copy).

But in Java, objects are unnamed. There are only references to them, which can be copied, but the object itself isn't copied. For the cases when you actually need to copy them, you can use the clone call (but i read in other anwers clone is flawed. i'm no java programmer so i cannot comment that). Since not the object itself is returned, but rather a reference to it, a clone function will suffice. Also a clone function can be overriden. That's not going to work with copy constructors. And incidentally, in C++ when you need to copy a polymorphic object, a clone function is required too. It's got a name, the so-called virtual copy constructor.

Johannes Schaub - litb
I think you mean "incidentally," not "accidentally."
Rob Kennedy
darn. i thought finally i could finish one answer withouth having that ugly "edited" label. hehe thanks for telling me 'bout it :)
Johannes Schaub - litb
May I ask what's the difference? (English is not my first language.)
Hosam Aly
accidentally means that it happened without purpose, but it's bad. incidentally means that it happened, but it's randomly. u say "incidentally" if you want to say "oh, and by the way...". note im no native english speaker either. i hope im right with this
Johannes Schaub - litb
Accidentally refers to an event and means something happened *unintentionally* and usually has connotations of being undesirable; incidentally, when referring to an event means something happened as a byproduct and has neutral connotations. In the usage above, incidentally means "by the way", that is, as a side note, off the main topic.
Software Monkey
oh, thanks software monkey for the explanation on that
Johannes Schaub - litb
+1  A: 

I think you haven't get the right point. I give you my two cents.

Fundamentally there's a problem: creating a clone of a class without knowing the exact class type. If you use copy constructor, you cannot.

Here is an example:

class A {
public A(A c) { aMember = c.aMember }
    int aMember;
}

class B : A {
public B(B c) : base(c) { bMember = c.bMember }
    int bMember;
}

class GenericContainer {
public GenericContainer(GenericContainer c) {
 // XXX Wrong code: if aBaseClass is an instance of B, the cloned member won't 
 // be a B instance!
 aBaseClass = new A(c.aBaseClass);
}
    A aBaseClass;
}

The Clone method, if declare virtual, could create the right class instance of the generic member.

An this problem is common to every language, C# C++ or Java...

Maybe this is what you was meaning, but I cannot understand this from any answer.

Luca
A: 

I think its only because once u have defined a copy constructor, you could never pass the reference itself again. (Unless it would have a function that does that...but thats not any easier than using the clone() method.) In C++ its not a problem: you can pass the whole object or its reference.

Regic