3

I remember seeing some clone() use in Java, and now I've noticed it in some C++ code. I notice them here on StackExchange as well:

Copying a Polymorphic object in C++

So, is it a 'Good Idea' to have clone methods? Or should copy constructors be sufficient?

einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • 1
    There may be a semantic difference between just wanting a shallow copy versus a deep copy, in which case a clone will be an explicit call to deep copy everything so it is a distinct copy rather than a 'reference' to a shared object depending on how you implement your assignment operator and copy constructor – EdChum Jul 17 '14 at 10:37
  • @EdChum: So, you're saying copy ctor = shallow, clone = deep essentially? – einpoklum Jul 17 '14 at 10:39
  • 1
    Languages with a garbage collector have *much* less of a need for copying objects. They can for example safely store a pointer to an object in a collection without having to worry about ownership and deterministic cleanup. So they don't have anything similar to a copy ctor. So if the programmer *wants* to provide copy semantics then he has to write an explicit method to generate the copy. Often called clone(). – Hans Passant Jul 17 '14 at 10:41
  • No I'm saying that it depends how you want to implement the copy constructor and assigment operator. If everything is `smart_ptr`'ed up and you are defining the contract as everything just gets a reference (via ptr) to the same object that is reference counted then that is fine, if instead you implement it as deep copy everything so everyone has their own copy then that is also fine but up to you. A Clone method is explicitly deep copying the object, you may prefer this as the name and functionality is explicit. – EdChum Jul 17 '14 at 10:42
  • 1
    @einpoklum No, copy constructor is assumed to be a deep copy by user code. – Neil Kirk Jul 17 '14 at 10:42
  • 1
    I have seen some people disallow the assignment and copy constructor so therefore you have to call `clone` to get a copy of the object but it really depends on the contract you want to define and honour – EdChum Jul 17 '14 at 10:43
  • 1
    The problem with polymorphism is you don't know the exact type that is being copied at compile time, which copy constructor requires. Hence a clone method, perhaps with disabled copy constructors for safety. Look up: object slicing. – Neil Kirk Jul 17 '14 at 10:43
  • @NeilKirk: Yes, got it. See TonyD's answer (and my comment) – einpoklum Jul 17 '14 at 11:17

2 Answers2

3

is it a 'Good Idea' to have clone methods? Or should copy ctors be sufficient?

Copy constructors can only copy the data members they know about - which excludes those in any derived object they may be embedded in. I.e. that's a problem if class X's copy constructor is used to copy an object address by an X* or X& but the actual runtime data object is of a derived type with additional data members.

A virtual clone method is an appropriate solution, letting the derived class specify code to use to copy objects of that type.

If you still can't clearly see the benefit, you should read up on O.O. design and polymorphism in general, then the need for this should start to become clear.

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
  • But then, doesn't it mean that clone() is _necessary_ for non-final classes? (i.e. classes which have subclasses)? – einpoklum Jul 17 '14 at 11:16
  • @einpoklum not quite... you may have no need to copy them, for example - if they're created by a factory then references/pointers are passed around, or it may be that you're copying but only in code that knows the runtime type at compile time (e.g. `Derived4 d; ...; Derived4 e(d);` or even `if (Derived2* p = dynamic_cast(p_base)) { Derived2* p_another = new Derived2(*p); ... }`). – Tony Delroy Jul 17 '14 at 12:25
  • Ok, let me rephrase that: Isn't a `clone()` necessary for classes which have subclasses, and that are copied around by code which is oblivious to the subclasses? – einpoklum Jul 17 '14 at 16:13
  • 1
    @einpoklum: almost, `virtual clone()` - and derived class implementations - are necessary for classes that have subclasses, where those subclasses are copied around by code that is oblivious to the subclasses. – Tony Delroy Jul 18 '14 at 07:47
  • Reading on OOP in general could give you a hint but I would say to read on that specific part as it is a more advanced topic in OOP. – Moataz Alsayed Dec 26 '20 at 08:54
-1

The reason for cloning is to create an exact duplicate of the object. So in worst case scenario, you will use twice the amount of memory. Because Strings are often interned and will not be cloned hence you might need to cast it. Although it is up to the implementor of the clone method/copy constructor to implement it.

  • And is this the single commonly-accepted semantic of cloning vs copy construction? – einpoklum Jul 17 '14 at 10:40
  • In C++, the Standard requires that a `std::string` that is copy-constructed from or assigned a value from another `std::string` will operate as if it's deep copied - your code never needs to "cast it" or do anything else unusual. If the implementation tries to do some clever "interning", it's the implementation's problem how to make sure your code still works unchanged (which is why I believe all early attempts at Copy-On-Write `std::string` implementations have been abandoned). – Tony Delroy Jul 17 '14 at 11:00
  • 1
    I don't understand this answer. Surely using twice the amount of memory is the best case, as you are creating a copy? The part about strings is too ambiguous to be useful. Perhaps you are referring to manually allocated arrays. – Neil Kirk Jul 17 '14 at 12:39