Ok so you mean to say that the default copy constructor's prototype
would be
You might want to consider dropping the term "default copy
constructor" to avoid the risk of confusion with the "default
constructor". In the context of constructors, "default" has a
precisely defined meaning which is not applicable here. "implicitly-
declared copy constructor" might be better (that appears to be what
the language standard uses). "Compiler-generated copy constructor" is
another fairly popular and uncontroversial name for it. But "default
copy constructor" should probably be avoided.
sample(sample&);
and my constructor's prototype would be
sample(sample)
and hence the compiler wouldn't know which call to resolve?
Nearly. Generally, the implicitly-generated copy constructor has the
signature sample(const sample&). Only if a base class or member of
sample does *not* have the const in the signature of its own copy
constructor, will the signature of sample's copy constructor be
sample(sampl&) as you wrote.
can you explain the recurssion part of it with an example?
Think about it. Whenever an object is passed to a function by value,
the copy constructor is needed to initialise the function parameters.
void foo(T t1, T t2) {}
int main()
{
T a, b;
foo(a, b);
}
In the line foo(a, b) a and b (which are objects of type T) are passed
to function foo and used to initialise foo's parameters t1 and t2
respectively. t1 is a copy of a. t2 is a copy of b. Surprise, surprise
- to create t1 and t2 as copies of a and b, the copy constructor of
class T is used. That's how you make copies of objects.
Now what actually happens when the copy constructor of class T is
used? Imagine class T's copy constructor looks like this
T(const T& src);
and we are using that copy constructor to construct t1 from the source
object, a. t1 is the object under construction, and src is a reference
to the source object, a. That's important. src is not an object. It is
just a reference to a, an object that already exists. Whatever the
body of the copy constructor needs to do to initialise the internals
of the new object t1, it can do, because it can get at the internals
of the source object, a, through the reference, src.
Now, imagine we tried to use your signature for the copy constructor
here
T(T src);
This time src is an object, so in the process of calling this copy
constructor, the object src needs to be constructed. We are trying to
copy-construct t1 as a copy of a. But before we can start doing
whatever is in the body of the copy constructor, we need to construct
src, the parameter of the copy constructor. How do we construct src?
Well it needs to be a copy of a so I guess we need to use the copy
constructor.
That's the recursion. The very first thing that happens when we try
and use the copy constructor (to create t1 from a) is that we need to
use the copy constructor (to create the copy constructor's own
parameter src from a). But the very first thing that happens when we
try and use the copy constructor (this time to construct src from a)
is that we need to use the copy constructor .... and so, ad infinitum.
Put another way, the conversation goes like:
Me: "I need to know how to copy objects of type T because I have to
make t1 as a copy of a".
You: "OK. First of all, create yourself an object of type T called src
by copying a".
Me: "But I don't know how to copy objects of type T. That's what I'm
asking you".
Gavin Deane