Copy constructors and clones

E

Edward Diener

Coming from the C++ world I can not understand the reason why copy
constructors are not used in the .NET framework. A copy constructor creates
an object from a copy of another object of the same kind. It sounds simple
but evidently .NET has difficulty with this concept for some reason. I do
understand that .NET objects are created on the GC heap but that doesn't
mean that they couldn't be copied from another object of the same kind when
they are created.

I understand that .NET has an ICloneable interface which is used to make a
deep copy of an object, and that it even has a protected MemberWiseClone to
be used internally for shallow copies. But much to my surprise even
ICloneable.Clone() is sometimes not used to make a deep copy of an object
but some other particular class member function is used instead.

As an example when I look at the system.string class I find that it does not
have a copy constructor, which for whatever reason I do not understand seems
normal for .NET. Then I look at the Clone() function, expecting it to make a
copy of the string's contents and return it to me as a new string. No, it
doesn't do that either. Finally I find the Copy() function which does the
job. So instead of creating a new string from an old one, I must do the
arcane ( for me ) 'string x = string.Copy(old_instance);' rather than a
simple 'string x = new string(old_instance)'.

Comments and explanations ?
 
C

Cor

Hi Edward

VB.net
dim newstring as string = oldstring
C#
string newstring = oldstring;
C++ as you said
string newstring = new string(oldstring)

I think you love to type?

Comments:

Never try to use your used old statements from you used language.

Example, once someone told me that in his language he only used 50 code for
a sort, he had translated it to the one I was using then and he 200 lines of
code

He had not seen that there was a statemen "sort" from one line.
(It was also much faster)

Cor
 
E

Edward Diener

Cor said:
Hi Edward

VB.net
dim newstring as string = oldstring
C#
string newstring = oldstring;

This assigns the reference of the oldstring to the newstring. It does not do
a copy.
C++ as you said
string newstring = new string(oldstring)

Wrong syntax. It would have to be:

String * newstring = new String(oldstring);

I don't see a constructor like this in the documentation. Does it really
exist for making a copy ? If so it is not documented.
I think you love to type?

No, I hate to type. That is why I brought up the subject in the first place.
I also find copy constructors easy to use in C++. However the example you
gave for C# does not do a copy and the corrected example for C++ does not
exist AFAIK. I don't know VB but I am guessing that it doesn't do a copy
either but rather creates another reference.
 
B

Bruno Jouhier [MVP]

As an example when I look at the system.string class I find that it does
not
have a copy constructor, which for whatever reason I do not understand seems
normal for .NET. Then I look at the Clone() function, expecting it to make a
copy of the string's contents and return it to me as a new string. No, it
doesn't do that either. Finally I find the Copy() function which does the
job. So instead of creating a new string from an old one, I must do the
arcane ( for me ) 'string x = string.Copy(old_instance);' rather than a
simple 'string x = new string(old_instance)'.

Strings are immutable. So you are basically wasting memory if you copy them.
Copying is only interesting if you can get a mutable copy.

Bruno.
 
C

Codemonkey

Cor,

As a string is a reference type, "dim newstring as string = oldstring"
causes "newstring" to point to the same string instance as "oldstring" (as
can be demonstrated by the Is operator). Some may mistakenly think that they
point to different instances because if you change "newstring", "oldstring"
doesn't change - this is because a string is immutable, not because there
are two string instances containing the same characters. If you done this
with an object that is not immutable, then it is not a copy, simply another
reference to the same object (unless you use a value type).

Back to Edwards question, I think that the lack of copy constructors in .net
is more of an oversight in the implementation of the object that you are
using, rather than a missing feature in the languages. Personally, I think
ICloneable is suitable - afterall not all objects can be cloned - those that
can't be cloned simply do not implement ICloneable. Also, there is nothing
to stop you implementing a copy constructor in your own objects.

As far as the documentation for the Clone method of a string is concerned it
states:

"The return value is not an independent copy of this instance; it is simply
another view of the same data. Use the Copy or CopyTo method to create a
separate String object with the same value as this instance."

Which kinda defeats the purpose of the Clone method in my opinion, but I
guess they had their reasons (probably because a string is immutable, so
changes will not affect other references to the same instance).

HTH,

Trev.
 
J

Jay B. Harlow [MVP - Outlook]

Edward,
In addition to Cor's comments.

There is nothing stopping you from defining a copy constructor in your
classes! In fact I use (protected) copy constructors to implement my Clone
methods in one of my projects, as you have to if you want to use read-only
fields in your class. :) Read-only fields can only be set in the
constructor, MemberWiseCopy was not an option as I need a deep copy...

IMHO The biggest advantage that the Clone Pattern has over copy constructors
is that the Clone pattern can be polymorphic. You can define Clone as
virtual/overridable in the base class, and offer implementation in the
derived classes. The other code can create a copy of that object, with only
a reference to the base object!

IMHO The second biggest advantage is consistency. If you need Clone for
polymorphism, having some classes implement clone while others implement
pure copy constructors leads to somewhat inconsistent code. Having all
objects that can be 'copied' implement the Clone pattern leads to code that
is quicker to understand (unless of course you can from a C++ background
;-)). Note some classes support Clone & Copy methods. Where Clone does a
"shallow" copy, while Copy does a "deep" copy. In addition to your String
example see System.Data.DataSet & System.Data.DataTable for examples.

IMHO the one danger of copy constructors are in class hierarchies like
System.IO.Stream. Is the stream object passed to the constructor of a
derived stream intended for a copy or are you implementing a
Composite/Delegate Pattern?

I want to say there are a handful of classes in the Framework that support
copy constructors, however I don't remember specifically which ones.
As an example when I look at the system.string class I find that it does
not
Remember that String is immutable reference type, I have yet to need to make
a copy of the contents of a string. I would do as Cor stated.

String x = old_instance

And live with the reference. In fact I would prefer to have the reference,
as it performs better & is easier on Memory consumption...

Hope this helps
Jay
 
E

Edward Diener

Bruno said:
Strings are immutable. So you are basically wasting memory if you
copy them. Copying is only interesting if you can get a mutable copy.

You are correct. Definitely my error for not realizing this.
 
E

Edward Diener

Codemonkey said:
Cor,

As a string is a reference type, "dim newstring as string = oldstring"
causes "newstring" to point to the same string instance as
"oldstring" (as can be demonstrated by the Is operator). Some may
mistakenly think that they point to different instances because if
you change "newstring", "oldstring" doesn't change - this is because
a string is immutable, not because there are two string instances
containing the same characters. If you done this with an object that
is not immutable, then it is not a copy, simply another reference to
the same object (unless you use a value type).

Yes, what I said in my reply. You gave an example of a reference assignment
and not a copy.
Back to Edwards question, I think that the lack of copy constructors
in .net is more of an oversight in the implementation of the object
that you are using, rather than a missing feature in the languages.

IMHO copy constructors are an easy way to construct a new object from an old
object of the same type.
Personally, I think ICloneable is suitable - afterall not all objects
can be cloned - those that can't be cloned simply do not implement
ICloneable.

And if an object is not cloneable, .NET objects should not implement a copy
constructor. The same argument holds.
Also, there is nothing to stop you implementing a copy
constructor in your own objects.

Of course not, but why the .NET framework objects don't have them was the
original query.
As far as the documentation for the Clone method of a string is
concerned it states:

"The return value is not an independent copy of this instance; it is
simply another view of the same data. Use the Copy or CopyTo method
to create a separate String object with the same value as this
instance."

Which kinda defeats the purpose of the Clone method in my opinion,
but I guess they had their reasons (probably because a string is
immutable, so changes will not affect other references to the same
instance).

I was wrong to bring up string. Since it is immutable, making a copy of it
is a waste of time. I now realize this. But having copy constructors for
mutable objects still seems like a good idea to me and I am still surprised
mutable FCL classes do not have them.
 
E

Edward Diener

Jay said:
Edward,
In addition to Cor's comments.

There is nothing stopping you from defining a copy constructor in your
classes!

Of course not.
In fact I use (protected) copy constructors to implement my
Clone methods in one of my projects, as you have to if you want to
use read-only fields in your class. :) Read-only fields can only be
set in the constructor, MemberWiseCopy was not an option as I need a
deep copy...

I agree.
IMHO The biggest advantage that the Clone Pattern has over copy
constructors is that the Clone pattern can be polymorphic. You can
define Clone as virtual/overridable in the base class, and offer
implementation in the derived classes. The other code can create a
copy of that object, with only a reference to the base object!

I don't see how ICloneable::Clone being polymorphic helps at all. Can you
give me an example ? I find it exactly otherwise and I see it hindering
things since I can not use the cloned object of a base class in my derived
class Clone(), since the base class
Clone() creates a separate object reference to the base class for me and yet
my derived class's Clone() has to return a reference to my derived class. So
in my Clone() for a derived class I must repeat everything I am doing in my
base class's Clone() plus any member variables that need to be cloned for my
derived class.

OTOH copy constructors have no such problems and are actually polymorphic by
nature. If my base class has a copy constructor, I simply call the base
class copy constructor passing the other object that needs to be copied to
the base class, then I copy any other non-base fields from the copied object
to my own. This is much easier and more natural than implementing Clone() in
a class hierarchy.
IMHO The second biggest advantage is consistency. If you need Clone
for polymorphism, having some classes implement clone while others
implement pure copy constructors leads to somewhat inconsistent code.

I can understand this as an inconsistency but I would rather have copy
constructors than cloneable objects ( see above ). The one advantage of
ICloneable as an interface is that one can test for it in code to see if an
object is cloneable. But I see little advantage for this at run-time.
Having all objects that can be 'copied' implement the Clone pattern
leads to code that is quicker to understand (unless of course you can
from a C++ background ;-)).

The smiley is noted. For C++ programmers copy constructors are much easier
to use and program. I still think they are in any application framework.
Note some classes support Clone & Copy
methods. Where Clone does a "shallow" copy, while Copy does a "deep"
copy. In addition to your String example see System.Data.DataSet &
System.Data.DataTable for examples.

Yes said:
IMHO the one danger of copy constructors are in class hierarchies like
System.IO.Stream. Is the stream object passed to the constructor of a
derived stream intended for a copy or are you implementing a
Composite/Delegate Pattern?

That is what documentation is all about. Normally the same object passed to
a copy constructor is always for copy however. If you need a composite, the
object can be passed in a member function.
I want to say there are a handful of classes in the Framework that
support copy constructors, however I don't remember specifically
which ones.

There may be some AFAIK but generally FCL does not support the idea of copy
constructors. Which is something I find a bit strange.
not
Remember that String is immutable reference type, I have yet to need
to make a copy of the contents of a string. I would do as Cor stated.

String x = old_instance

And live with the reference. In fact I would prefer to have the
reference, as it performs better & is easier on Memory consumption...

This was definitely my mistake in using an immutable object as an example.
String doesn't need a copy constructor and even the String::Copy member
function seems a waste of time to me.
Hope this helps

Except for the ICloneable interface telling code at run-time that an object
is cloneable, I don't see eveidence that it is preferable to copy
constructors and all my experience points the other way. I will be glad to
look at evidence which favors ICloneable if you would like to present it.
Sometimes older, time-tested ideas are best.
 
C

Cor

Hi Edward,
This was definitely my mistake in using an immutable object as an example.
String doesn't need a copy constructor and even the String::Copy member
function seems a waste of time to me.

And therefore I was so fast with my answer, with a smile on my face when I
was writting it.

:))

Cor
 
J

Jay B. Harlow [MVP - Outlook]

Edward,
OTOH copy constructors have no such problems and are actually polymorphic by
nature. If my base class has a copy constructor, I simply call the base
class copy constructor passing the other object that needs to be copied to
the base class, then I copy any other non-base fields from the copied object
to my own. This is much easier and more natural than implementing Clone() in
a class hierarchy.

Can you give a C++ example seem to be missing something in your explanation.
It may be my just being away from C++ too long. ;-)

With a copy constructor: If I have an object that is actually type Derived
in a Base variable, to create a copy of Derived I would need to call new
Derived(oldBase). correct?

// Given:
// Consider that new Derived may have come from a factory method
Base oldBase = new Derived();

// elsewhere where we don't know what the concrete type of oldBase is:
// What do you put for the new type in the following statement?
// considering that I want the exact same type back?
Base copyBase = new ????(oldBase);

With the Clone pattern I can simply call the Clone method, having defined
Clone method as virtual in Base & Derived.

Base copyBase = oldBase.Clone();
// copyBase will still be a Derived object.

The Clone method itself acts as the Factory Method to ensure the correct
type of derived object is created.
The smiley is noted. For C++ programmers copy constructors are much easier
to use and program. I still think they are in any application framework.
When I programmed in C++ I would have agreed with you! Now I think I'm so
use to them not being available in Java or .NET that I really don't miss
them. However I do consider myself fortunate to have used them in C++ to be
able to apply them to good use in my class families (in Java or .NET).

Hope this helps
Jay
 
E

Edward Diener

Jay said:
Edward,

Can you give a C++ example seem to be missing something in your
explanation. It may be my just being away from C++ too long. ;-)

In standard C++:

class Base
{
public:
int i;
Base() { i = 0; }
Base(const Base & b) { i = b.i; }
};

class Derived : public Base
{
public:
double db;
Derived() { db = 1.0; }
Derived(const Derived & d) : Base(d) { db = d.db; }
};

Derived dfirst; // Default constructor
Derived dsecond(dfirst); // Copy constructor

When you invoke Derived's copy constructor, it passes the reference to
Base's copy constructor. Since a Derived contains a Base, there is no
problem for Base initializing its own variable(s) from that copy. The
compiler automatically downcasts from a Derived reference to a Base
reference when passing copy constructors down the chain.
With a copy constructor: If I have an object that is actually type
Derived in a Base variable, to create a copy of Derived I would need
to call new Derived(oldBase). correct?

No, see above.
// Given:
// Consider that new Derived may have come from a factory method
Base oldBase = new Derived();

In C++ this is:

Base * oldBase = new Derived();
// elsewhere where we don't know what the concrete type of oldBase is:
// What do you put for the new type in the following statement?
// considering that I want the exact same type back?
Base copyBase = new ????(oldBase);

If you do:

Base * copyBase = new Derived(*oldBase);

you get a compiler error since you are passing a reference to a base and the
Derived's copy constructor expects a reference to a Derived. If you do:

Base * copyBase = new Derived(dynamic_cast<Derived &>(*oldBase));

you are fine as long as oldBase is really pointing to a derived object. If
it is not, that is your fault and you will get a bad_cast exception thrown.
The Derived class's copy constructor above expects a Derived object. Of
course you can add another copy constructor to Derived that takes a 'const
Base &' like this:

Derived(const Base & b) : Base(b) { db = 1.0; }

and now you are successful doing:

Base * copyBase = new Derived(*oldBase);

and then you can pass Base or Derived references to it. In this sense C++
copy constructors are not polymorphic, and I shouldn't have said that. It
was bad wording and the word polymorphic was wrong. C++ constructors are not
virtual and work on the static type, not the dynamic type. What I meant to
say is that derived class objects can be passed down to base class copy
constructors through automatic downcasting. I consider this much better in
this particular case than polymorphism.
With the Clone pattern I can simply call the Clone method, having
defined Clone method as virtual in Base & Derived.

Base copyBase = oldBase.Clone();
// copyBase will still be a Derived object.

You can create a base object from a derived copy also.

Derived d;
Base * b(new Base(d));

is perfectly fine in C++. The compiler will automatically downcast from a
derived reference to a base reference when creating the new Base by passing
it a Derived reference, and accept it. Base's copy constructor will accept a
derived reference based on Derived being derived from Base and therefore
holding a Base within itself. This is no different from your Clone()
polymorphism as you call it said:
The Clone method itself acts as the Factory Method to ensure the
correct type of derived object is created.

The problem is implementing the Clone() method. You have to repeat all the
initializations of your base class, which might be voluminous. In copy
constructors, you just pass your object down to the base class and each base
class initializes its own variables. There is no repeat initializations.

As a matter of fact, if a base class in a framework using Clone() has
private variables which need to be initialized, and since private variables
are completely inaccessible to the derived class, I don't even understand
how Clone() can even work at all, since it is impossible for the derived
class to properly initialize the base class's private variables. With copy
construction this problem does not exist.

I consider Clone() an essentially broken idea except for very independent
objects, but even there copy constructors are superior. They are easier to
code and use and are more robust.

But maybe I have missed something. If so, please enlighten me.

Eddie
 
J

Jay B. Harlow [MVP - Outlook]

Edward,
But maybe I have missed something. If so, please enlighten me.
Unfortunately I know my limitations! ;-)

(sincerely not meant as a slam against you or anyone!).
Derived d;
Base * b(new Base(d));

is perfectly fine in C++. The compiler will automatically downcast from a
derived reference to a base reference when creating the new Base by passing
it a Derived reference, and accept it. Base's copy constructor will accept a
derived reference based on Derived being derived from Base and therefore
holding a Base within itself. This is no different from your Clone()
polymorphism as you call it, but without the 'polymorphism' <g> .
Huh? "new Base(d)" gives you a Base object not a Derived object, or is there
some new obscure rule going on here to enable C++ code to be even more
confusing?

The point of my suggesting using polymorphism is to get a Derived object out
if you have a Derived object in. As far as I can tell the above paragraph
says, Create a new Base object, that holds a reference to a Derived object
(which is composition, not copying!).

I really don't have any thing further to add to my original comments, you
are welcome to my original comments for what they are worth. I hope you
understand if I drop out of this discussion.

Hope this helps
Jay
 
C

Codemonkey

The problem is implementing the Clone() method.
You have to repeat all the
initializations of your base class, which might be voluminous.
.......

I don't even understand
how Clone() can even work at all,
since it is impossible for the derived
class to properly initialize the base
class's private variables

Good point. I never thought of it it this way. I guess it's becoming clearer
to me why copy constructors can be a great idea sometimes.

As for your origional wondering why the FCL doesn't employ copy constructors
more often... maybe the people in charge of design didn't have your
foresight ;)

Thanks for your thoughts on this... I've found it interesting and maybe will
try to use copy constructors more often.

Trev.
 
E

Edward Diener

Jay said:
Edward,
Unfortunately I know my limitations! ;-)

(sincerely not meant as a slam against you or anyone!).

Huh? "new Base(d)" gives you a Base object not a Derived object, or
is there some new obscure rule going on here to enable C++ code to be
even more confusing?

Where do I say that "new Base(d)" gives one a Derived * object ? Clearly
above it gives one Base * object which one assigns to the Base * b variable.
The point of my suggesting using polymorphism is to get a Derived
object out if you have a Derived object in. As far as I can tell the
above paragraph says, Create a new Base object, that holds a
reference to a Derived object (which is composition, not copying!).

No, it accepts a reference to a Derived object passed to it in its
"Base(const Base &)" constructor. The compiler automatically downcasts the
"const Derived &" that is passed to it as a "const Base &". That is a copy
constructor. It doesn't mean that base "holds a reference to a Derived
object". It simply means it uses the Base portion of the Derived reference
passed to it to initialize its own variables by copying the Base values
passed in to it.
I really don't have any thing further to add to my original comments,
you are welcome to my original comments for what they are worth. I
hope you understand if I drop out of this discussion.

No problem. I wasn't trying to initimidate anyone or be egotistical, just
attempting to clarify the use of Clone() over copy constructors in the .NET
framework classes. As I said, for me coming from largely the C++ world, copy
constructors are definitely better. They are easier to write and ensure that
an object is constructed based on another copy of the same type of object,
and they work throughout a base/derived framework. The Clone() method looks
nice but, as I have discovered, is difficult to implement and has holes when
it comes to cloning base class fields when those fields are private. The one
upside to Clone() and ICloneable is that one can test an object at run-time
to see if it is cloneable. This doesn't make up for me the downside of
Clone() which I have already mentioned.
 
E

Edward Diener

Codemonkey said:
Good point. I never thought of it it this way. I guess it's becoming
clearer to me why copy constructors can be a great idea sometimes.

As for your origional wondering why the FCL doesn't employ copy
constructors more often... maybe the people in charge of design
didn't have your foresight ;)

Thanks for the compliment as it is appreciated. MS has done C++ very well,
especially under Stan Lippman, so maybe they should have spoken to their own
C++ development team to discover why copy constructors are better than
Clone() in the FCL.

As for my foresight, I wish employers would recognize it and hire me for a
job where I could make a living. That would lessen the pain of using Clone()
instead of copy constructors for current FCL classes said:
Thanks for your thoughts on this... I've found it interesting and
maybe will try to use copy constructors more often.

Good luck !
 
J

Jay B. Harlow [MVP - Outlook]

Edward,
The Clone() method looks
nice but, as I have discovered, is difficult to implement and has holes when
it comes to cloning base class fields when those fields are private.
Which is why I implemented Clone in the terms of a copy constructor ;-)

Coming from C++ Clone is definitely different, however I don't find it
difficult per se.

Something like (VB.NET)

Public Class Base
Implements ICloneable

Private Readonly m_name As String

Public Sub New(ByVal name As string)
m_name = name
End

Protected Sub New(ByVal other As Base)
m_name = other.m_name
End Sub

Public Overridable Function Clone() As Object Implements
ICloneable.Clone
Return New Base(Me)
End Sub

End Class

Public Class Derived
Inherits Base

Private Readonly m_stuff As Integer

Public Sub New(ByVal name As String, ByVal stuff As Integer)
MyBase.New(name)
m_stuff = stuff
End Sub

Protected Sub New(ByVal other As Derived)
Mybase.New(other)
m_stuff = other.m_stuff
End Sub

Public Overrides Function Clone() As Object
Return New Derived(Me)
End Sub

End Class

Public Module TestModule

Public Sub Main()
Dim b1 As New Base("jay")
Dim b2 As New Derived("Edward", 1)
ProcessClone(b1)
ProcessClone(b2)
End Sub

Public Sub ProcessClone(ByVal b As Base)
Dim newBase As Base = DirectCast(b.Clone(), Base)
Debug.WriteLine(b Is newBase, "b Is newBase")
Debug.WriteLine(b.GetType(), "b type")
Debug.WriteLine(newBase.GetType(), "newBase type")
End Sub

End Module

The copy constructor is an implementation detail, hence its protected.

If you want a C# or C++ version I can see what I can do.

Hope this helps
Jay


Edward Diener said:
Jay said:
Edward,
Unfortunately I know my limitations! ;-)

(sincerely not meant as a slam against you or anyone!).

Huh? "new Base(d)" gives you a Base object not a Derived object, or
is there some new obscure rule going on here to enable C++ code to be
even more confusing?

Where do I say that "new Base(d)" gives one a Derived * object ? Clearly
above it gives one Base * object which one assigns to the Base * b variable.
The point of my suggesting using polymorphism is to get a Derived
object out if you have a Derived object in. As far as I can tell the
above paragraph says, Create a new Base object, that holds a
reference to a Derived object (which is composition, not copying!).

No, it accepts a reference to a Derived object passed to it in its
"Base(const Base &)" constructor. The compiler automatically downcasts the
"const Derived &" that is passed to it as a "const Base &". That is a copy
constructor. It doesn't mean that base "holds a reference to a Derived
object". It simply means it uses the Base portion of the Derived reference
passed to it to initialize its own variables by copying the Base values
passed in to it.
I really don't have any thing further to add to my original comments,
you are welcome to my original comments for what they are worth. I
hope you understand if I drop out of this discussion.

No problem. I wasn't trying to initimidate anyone or be egotistical, just
attempting to clarify the use of Clone() over copy constructors in the ..NET
framework classes. As I said, for me coming from largely the C++ world, copy
constructors are definitely better. They are easier to write and ensure that
an object is constructed based on another copy of the same type of object,
and they work throughout a base/derived framework. The Clone() method looks
nice but, as I have discovered, is difficult to implement and has holes when
it comes to cloning base class fields when those fields are private. The one
upside to Clone() and ICloneable is that one can test an object at run-time
to see if it is cloneable. This doesn't make up for me the downside of
Clone() which I have already mentioned.
Hope this helps
Jay

Edward Diener said:
Jay B. Harlow [MVP - Outlook] wrote:
Edward,
OTOH copy constructors have no such problems and are actually
polymorphic by nature. If my base class has a copy constructor, I
simply call the base class copy constructor passing the other
object that needs to be copied to the base class, then I copy any
other non-base fields from the copied object to my own. This is
much easier and more natural than implementing Clone() in a class
hierarchy.

Can you give a C++ example seem to be missing something in your
explanation. It may be my just being away from C++ too long. ;-)

In standard C++:

class Base
{
public:
int i;
Base() { i = 0; }
Base(const Base & b) { i = b.i; }
};

class Derived : public Base
{
public:
double db;
Derived() { db = 1.0; }
Derived(const Derived & d) : Base(d) { db = d.db; }
};

Derived dfirst; // Default constructor
Derived dsecond(dfirst); // Copy constructor

When you invoke Derived's copy constructor, it passes the reference
to Base's copy constructor. Since a Derived contains a Base, there
is no problem for Base initializing its own variable(s) from that
copy. The compiler automatically downcasts from a Derived reference
to a Base reference when passing copy constructors down the chain.


With a copy constructor: If I have an object that is actually type
Derived in a Base variable, to create a copy of Derived I would need
to call new Derived(oldBase). correct?

No, see above.


// Given:
// Consider that new Derived may have come from a factory method
Base oldBase = new Derived();

In C++ this is:

Base * oldBase = new Derived();


// elsewhere where we don't know what the concrete type of oldBase
is: // What do you put for the new type in the following statement?
// considering that I want the exact same type back?
Base copyBase = new ????(oldBase);

If you do:

Base * copyBase = new Derived(*oldBase);

you get a compiler error since you are passing a reference to a base
and the Derived's copy constructor expects a reference to a Derived.
If you do:

Base * copyBase = new Derived(dynamic_cast<Derived &>(*oldBase));

you are fine as long as oldBase is really pointing to a derived
object. If it is not, that is your fault and you will get a bad_cast
exception thrown. The Derived class's copy constructor above expects
a Derived object. Of course you can add another copy constructor to
Derived that takes a 'const Base &' like this:

Derived(const Base & b) : Base(b) { db = 1.0; }

and now you are successful doing:

Base * copyBase = new Derived(*oldBase);

and then you can pass Base or Derived references to it. In this
sense C++ copy constructors are not polymorphic, and I shouldn't
have said that. It was bad wording and the word polymorphic was
wrong. C++ constructors are not virtual and work on the static type,
not the dynamic type. What I meant to say is that derived class
objects can be passed down to base class copy constructors through
automatic downcasting. I consider this much better in this
particular case than polymorphism.


With the Clone pattern I can simply call the Clone method, having
defined Clone method as virtual in Base & Derived.

Base copyBase = oldBase.Clone();
// copyBase will still be a Derived object.

You can create a base object from a derived copy also.

Derived d;
Base * b(new Base(d));

is perfectly fine in C++. The compiler will automatically downcast
from a derived reference to a base reference when creating the new
Base by passing it a Derived reference, and accept it. Base's copy
constructor will accept a derived reference based on Derived being
derived from Base and therefore holding a Base within itself. This
is no different from your Clone() polymorphism as you call it, but
without the 'polymorphism' <g> .


The Clone method itself acts as the Factory Method to ensure the
correct type of derived object is created.

The problem is implementing the Clone() method. You have to repeat
all the initializations of your base class, which might be
voluminous. In copy constructors, you just pass your object down to
the base class and each base class initializes its own variables.
There is no repeat initializations.

As a matter of fact, if a base class in a framework using Clone() has
private variables which need to be initialized, and since private
variables are completely inaccessible to the derived class, I don't
even understand how Clone() can even work at all, since it is
impossible for the derived class to properly initialize the base
class's private variables. With copy construction this problem does
not exist.

I consider Clone() an essentially broken idea except for very
independent objects, but even there copy constructors are superior.
They are easier to code and use and are more robust.

But maybe I have missed something. If so, please enlighten me.

Eddie
 
E

Edward Diener

Jay said:
Edward,
Which is why I implemented Clone in the terms of a copy constructor
;-)

Coming from C++ Clone is definitely different, however I don't find it
difficult per se.

Something like (VB.NET)

Public Class Base
Implements ICloneable

Private Readonly m_name As String

Public Sub New(ByVal name As string)
m_name = name
End

Protected Sub New(ByVal other As Base)
m_name = other.m_name
End Sub

Public Overridable Function Clone() As Object Implements
ICloneable.Clone
Return New Base(Me)
End Sub

End Class

Public Class Derived
Inherits Base

Private Readonly m_stuff As Integer

Public Sub New(ByVal name As String, ByVal stuff As Integer)
MyBase.New(name)
m_stuff = stuff
End Sub

Protected Sub New(ByVal other As Derived)
Mybase.New(other)
m_stuff = other.m_stuff
End Sub

Public Overrides Function Clone() As Object
Return New Derived(Me)
End Sub

End Class

Public Module TestModule

Public Sub Main()
Dim b1 As New Base("jay")
Dim b2 As New Derived("Edward", 1)
ProcessClone(b1)
ProcessClone(b2)
End Sub

Public Sub ProcessClone(ByVal b As Base)
Dim newBase As Base = DirectCast(b.Clone(), Base)
Debug.WriteLine(b Is newBase, "b Is newBase")
Debug.WriteLine(b.GetType(), "b type")
Debug.WriteLine(newBase.GetType(), "newBase type")
End Sub

End Module

The copy constructor is an implementation detail, hence its protected.

If you want a C# or C++ version I can see what I can do.

I am fine with the VB since it is easy to understand. I understand what you
are doing by using the copy constructor to implement Clone(). I find this
works well and I appreciate the technique. Thanks ! I still prefer a public
copy constructor, because the syntax of creating a new object using a public
copy constructor is more natural for me, but implementing Clone() in turns
of a protected copy constructor is just as good and gives you the advantage
of tagging your class as cloneable.
Hope this helps
Jay


Edward Diener said:
Jay said:
Edward,
But maybe I have missed something. If so, please enlighten me.
Unfortunately I know my limitations! ;-)

(sincerely not meant as a slam against you or anyone!).

Derived d;
Base * b(new Base(d));

is perfectly fine in C++. The compiler will automatically downcast
from a derived reference to a base reference when creating the new
Base by passing it a Derived reference, and accept it. Base's copy
constructor will accept a derived reference based on Derived being
derived from Base and therefore holding a Base within itself. This
is no different from your Clone() polymorphism as you call it, but
without the 'polymorphism' <g> .
Huh? "new Base(d)" gives you a Base object not a Derived object, or
is there some new obscure rule going on here to enable C++ code to
be even more confusing?

Where do I say that "new Base(d)" gives one a Derived * object ?
Clearly above it gives one Base * object which one assigns to the
Base * b variable.
The point of my suggesting using polymorphism is to get a Derived
object out if you have a Derived object in. As far as I can tell the
above paragraph says, Create a new Base object, that holds a
reference to a Derived object (which is composition, not copying!).

No, it accepts a reference to a Derived object passed to it in its
"Base(const Base &)" constructor. The compiler automatically
downcasts the "const Derived &" that is passed to it as a "const
Base &". That is a copy constructor. It doesn't mean that base
"holds a reference to a Derived object". It simply means it uses the
Base portion of the Derived reference passed to it to initialize its
own variables by copying the Base values passed in to it.
I really don't have any thing further to add to my original
comments, you are welcome to my original comments for what they are
worth. I hope you understand if I drop out of this discussion.

No problem. I wasn't trying to initimidate anyone or be egotistical,
just attempting to clarify the use of Clone() over copy constructors
in the .NET framework classes. As I said, for me coming from largely
the C++ world, copy constructors are definitely better. They are
easier to write and ensure that an object is constructed based on
another copy of the same type of object, and they work throughout a
base/derived framework. The Clone() method looks nice but, as I have
discovered, is difficult to implement and has holes when it comes to
cloning base class fields when those fields are private. The one
upside to Clone() and ICloneable is that one can test an object at
run-time to see if it is cloneable. This doesn't make up for me the
downside of Clone() which I have already mentioned.
Hope this helps
Jay

Jay B. Harlow [MVP - Outlook] wrote:
Edward,
OTOH copy constructors have no such problems and are actually
polymorphic by nature. If my base class has a copy constructor, I
simply call the base class copy constructor passing the other
object that needs to be copied to the base class, then I copy any
other non-base fields from the copied object to my own. This is
much easier and more natural than implementing Clone() in a class
hierarchy.

Can you give a C++ example seem to be missing something in your
explanation. It may be my just being away from C++ too long. ;-)

In standard C++:

class Base
{
public:
int i;
Base() { i = 0; }
Base(const Base & b) { i = b.i; }
};

class Derived : public Base
{
public:
double db;
Derived() { db = 1.0; }
Derived(const Derived & d) : Base(d) { db = d.db; }
};

Derived dfirst; // Default constructor
Derived dsecond(dfirst); // Copy constructor

When you invoke Derived's copy constructor, it passes the reference
to Base's copy constructor. Since a Derived contains a Base, there
is no problem for Base initializing its own variable(s) from that
copy. The compiler automatically downcasts from a Derived reference
to a Base reference when passing copy constructors down the chain.


With a copy constructor: If I have an object that is actually type
Derived in a Base variable, to create a copy of Derived I would
need to call new Derived(oldBase). correct?

No, see above.


// Given:
// Consider that new Derived may have come from a factory method
Base oldBase = new Derived();

In C++ this is:

Base * oldBase = new Derived();


// elsewhere where we don't know what the concrete type of oldBase
is: // What do you put for the new type in the following
statement? // considering that I want the exact same type back?
Base copyBase = new ????(oldBase);

If you do:

Base * copyBase = new Derived(*oldBase);

you get a compiler error since you are passing a reference to a
base and the Derived's copy constructor expects a reference to a
Derived. If you do:

Base * copyBase = new Derived(dynamic_cast<Derived &>(*oldBase));

you are fine as long as oldBase is really pointing to a derived
object. If it is not, that is your fault and you will get a
bad_cast exception thrown. The Derived class's copy constructor
above expects a Derived object. Of course you can add another copy
constructor to Derived that takes a 'const Base &' like this:

Derived(const Base & b) : Base(b) { db = 1.0; }

and now you are successful doing:

Base * copyBase = new Derived(*oldBase);

and then you can pass Base or Derived references to it. In this
sense C++ copy constructors are not polymorphic, and I shouldn't
have said that. It was bad wording and the word polymorphic was
wrong. C++ constructors are not virtual and work on the static
type, not the dynamic type. What I meant to say is that derived
class objects can be passed down to base class copy constructors
through automatic downcasting. I consider this much better in this
particular case than polymorphism.


With the Clone pattern I can simply call the Clone method, having
defined Clone method as virtual in Base & Derived.

Base copyBase = oldBase.Clone();
// copyBase will still be a Derived object.

You can create a base object from a derived copy also.

Derived d;
Base * b(new Base(d));

is perfectly fine in C++. The compiler will automatically downcast
from a derived reference to a base reference when creating the new
Base by passing it a Derived reference, and accept it. Base's copy
constructor will accept a derived reference based on Derived being
derived from Base and therefore holding a Base within itself. This
is no different from your Clone() polymorphism as you call it, but
without the 'polymorphism' <g> .


The Clone method itself acts as the Factory Method to ensure the
correct type of derived object is created.

The problem is implementing the Clone() method. You have to repeat
all the initializations of your base class, which might be
voluminous. In copy constructors, you just pass your object down to
the base class and each base class initializes its own variables.
There is no repeat initializations.

As a matter of fact, if a base class in a framework using Clone()
has private variables which need to be initialized, and since
private variables are completely inaccessible to the derived
class, I don't even understand how Clone() can even work at all,
since it is impossible for the derived class to properly
initialize the base class's private variables. With copy
construction this problem does not exist.

I consider Clone() an essentially broken idea except for very
independent objects, but even there copy constructors are superior.
They are easier to code and use and are more robust.

But maybe I have missed something. If so, please enlighten me.

Eddie
 
D

Daniel O'Connell

Edward Diener said:
Thanks for the compliment as it is appreciated. MS has done C++ very well,
especially under Stan Lippman, so maybe they should have spoken to their own
C++ development team to discover why copy constructors are better than
Clone() in the FCL.

From what I've read I'd argue that copy constructors are not better, but a
more risky construct. Considering the Composition arguments combined with
not being able to copy an object safely as its concrete type(and downcast to
the variable type) without knowing the type ahead of time, or that without
documentation you cannot know for sure that you are calling a copy
constructor, not just a badly typed constructor, or an ambigious constructor
call using some of the more complicated language rules that not everyone is
familiar with, I'd call Copy Constructors a technique that lacks a good deal
of grace.
Calling Clone tells me I have a copy of an object, new
myObject(myObjectReference) leaves me wondering if I'll get a copy or a
aggregate object, or simply an object that takes a limited set of settings
from another object(perhaps preferences without data). It also guarentees
that I won't lose any data that makes sense to copy. A copy constructor very
well could ignore many fields which shouldn't be dumped, simply because you
called a base constructor instead of the concrete type constructor. I don't
consider a copy without copying ALL relevent data a copy, but more of a near
type conversion. It also doesn't help as far as interfaces go, how exactly
do you clone an object that implements, say, IMyDataObject with a copy
constructor? What constructor do you call?
Is there an argument for why copy constructors are better, other than simply
because they are easier(for you) to type? The ease of constructors calling
eachother doesn't hold up, you can use protected constructors or a protected
virtual method to do the same thing: protected virtual Clone(BaseType
sourceObj, BaseType newObj); in a polymorphic fashion(although it'd require
some casting and type checking), depending on your needs. And I personally
find that calling new to create a copy is not anywhere near as clear, from a
maintainablitiy and readability standpoint as .Clone() is. The only argument
I've seen for copy constructors is that its easier for C++ developers to
use, and an unsubstantiated "its better".
Please, explain why its better, not simply by basing it on C++, but on
technical, .NET reasons its better. This is not an entirely C++ world, and
some pieces of C++ are probably better lost.
 
E

Edward Diener

Daniel said:
From what I've read I'd argue that copy constructors are not better,
but a more risky construct.

What that you have read about them that leads you to believe this ? Please
give technical arguments.
Considering the Composition arguments
combined with not being able to copy an object safely as its concrete
type(and downcast to the variable type) without knowing the type
ahead of time

Come again ? A copy constructor always defines the type which is to be
copied at compile time as part of the signature of the constructor. I have
no idea to what the term "Composition arguments" refers.
, or that without documentation you cannot know for sure
that you are calling a copy constructor, not just a badly typed
constructor, or an ambigious constructor call using some of the more
complicated language rules that not everyone is familiar with

Without documentation programmers are going to suffer no matter what your
methods are called. Why would anyone want to create a badly typed
constructor, and how would this differ from a badly implemented Clone()
method ? As far as "complicated language rules that not everyone is familiar
with", programming is not a popularity contest nor are copy constructors any
more complicated than any other language construct.
, I'd
call Copy Constructors a technique that lacks a good deal of grace.

If your opposition to copy constructors are that they are not aesthetically
pleasing to you, it is probably because you haven't used them very much. I
assume that is what you mean by "grace" in this context.
Calling Clone tells me I have a copy of an object, new
myObject(myObjectReference) leaves me wondering if I'll get a copy or
a aggregate object, or simply an object that takes a limited set of
settings from another object(perhaps preferences without data).

"Using a copy constructor tells me I have a copy of an object, while calling
Clone() leaves me wondering if I'll get a copy or a aggregate object, or
simply an object that takes a limited set of settings from another
object(perhaps preferences without data)."
It
also guarentees that I won't lose any data that makes sense to copy.
A copy constructor very well could ignore many fields which shouldn't
be dumped, simply because you called a base constructor instead of
the concrete type constructor. I don't consider a copy without
copying ALL relevent data a copy, but more of a near type conversion.

What is relevant data is determined by the designer of the classes in the
hierarchy in which the copy constructor resides. Why is Clone() any better ?
What guarantee do I have that all relevant data has been copied from the
current object and its base classes into the object I have cloned ? It is
once again a decision of the designer of the class.
It also doesn't help as far as interfaces go, how exactly do you
clone an object that implements, say, IMyDataObject with a copy
constructor?

Interfaces are member function contracts and do not contain data AFAIK.
What constructor do you call?

See above.
Is there an argument for why copy constructors are better, other than
simply because they are easier(for you) to type? The ease of
constructors calling eachother doesn't hold up

It certainly is easier to call the base class's constructor to initialize
base class data from a copy, and initialize just the data in your own class
from a copy, than having to initialize all data in all base classes
including your own class from a copy. I believe you have to be kidding to
feel otherwise. As I also previously pointed out, there is no way to
initialize private base class data in my derived class when doing Clone()
since I have no access to it. But that is not a problem using copy
constructors since each class in hierarchy initializes its own data from
the copy used to construct the original object.
, you can use protected
constructors or a protected virtual method to do the same thing:
protected virtual Clone(BaseType sourceObj, BaseType newObj); in a
polymorphic fashion(although it'd require some casting and type
checking), depending on your needs.

I have no issue with protected copy constructors. Another poster gave me a
very good method of implementing Clone() using protected copy constructors.
That just shows me that the copy constructor technique is not flawed. That
technique is certainly a workable implementation for Clone() and the only
way to copy private data from the base class.
And I personally find that
calling new to create a copy is not anywhere near as clear, from a
maintainablitiy and readability standpoint as .Clone() is.

Again that is an aesthetic call. If you have programmed in a language where
copy constructors create an easy to program methodology of creating an
object based on another object of the same type, than copy constructors are
more natural than Clone().
The only
argument I've seen for copy constructors is that its easier for C++
developers to use, and an unsubstantiated "its better".
Please, explain why its better, not simply by basing it on C++, but on
technical, .NET reasons its better. This is not an entirely C++
world, and some pieces of C++ are probably better lost.

I have explained why it is better a number of times in this thread. However
the technique of creating Clone() using a protected copy constructor is fine
with me, and does have the added attraction that once I implement it, other
objects know I am cloneable. I don't believe your own arguments have
technical merit but rely on aesthetics and "unknown" sources. Please argue
the technical issues youirself and not bring up language prejudices. I am
not supporting copy constructors because it is C++ but because it is an easy
and safe method to create an object based on another object. If it can be
abused, it is no different from an implementer of Clone() abusing that
functionality. Finally, as I have repeatedly shown, unless Clone() is
implemented using copy constructors, it is broken if base classes have
private data that need to be cloned also.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top