Assume the following class declaration:
class X { int p; ... public: X( int p1 ) : p(p1) { ... } // (a) X ( const X& x1 ) { ... } // (b) X& operator= (const X& x2 ) { ... } // (c) ... // member functions etc. void merge ( X x3 ) { .... } // (d) };
A line that begins with an X is a declaration of one
or more new objects of type X (the same is true for any other type specifier,
e.g. int or string). Consequently, one of the class
constructors is called. Constructors (as well as C++ functions
in general) can be overloaded, that is, the ones with the
same name but different argument lists are considered different,
and the compiler decides which one to use for a particular function
call by looking at the list of the actual arguments passed to
the function, and comparing their arguments with those of the known
function prototypes (all of this happens at compile time -- the C++ compiler deduces the types
of all expressions in your program). Therefore, the right constructor
to call is chosen by looking at the list of arguments it receives;
if no arguments are given, the default constructor X() for the
class is used (but see below).
X a( 10 ), a1( 100 );
Constructor (a) is called twice.
X b;
Illegal. This would call the constructor X(); However, it is
not defined for class X . Had the constructor (a) not been defined,
an automatically created default constructor would have been used,
but in the presence of other constructors explicitly defined for
X by the user this doesn't happen, and compilation fails
with an error. An explicit definition of X() is needed to make
this line legal.
X c = 12;
This calls constructor (a) with integer argument 12. Equivalent
forms: X c(12); and X
c = X(12);
X c1 = a1;
This calls the copy constructor (b). This decision is again based
the type of the RHS, which is interpreted as the argument to the
constructor. Please note that this line has nothing to do with
the overloaded assignment operator=. Operator= can be used only
when both LHS and RHS objects exist, while here c has yet to be
created. Therefore this amounts to calling a constructor, and
the type of the argument (class X) suggests (b).
X d( a );
A call to (b).
X e( 5, 18 );
Illegal. This would call a constructor X( int, int ). Since no
such constructor is defined, the line is illegal.
cout << a.p + a1.p << endl;
Illegal. The member p is private in X, so it cannot be accessed
via "dot" (aka the member selection operator).
a1 = a;
Overloaded assignment (c). Think of it as
a1.operator=(a);
d.merge( a );
Calls method (d), but first a copy of object a
needs to be created, so the copy constructor is called first.
Had the argument to merge
been declared as X& rather than X, there would be no need
to call a copy constructor.
X arr[ 15 ];
Illegal. This would create an array of 15 elements of type X.
Creating each of these means calling a constructor; since no argument
for the constructor is in sight, the constructor X() would be
called. Had X(int) not been defined, the automatically created
default constructor X() would have been called 15 times, but for
the present definition of class X this line produces and error.
Define some X() explicitly to allow the creation of array arr.
X f = X( -1 ) * X ( -2 );
Illegal. Two calls to (a) create two temporaries of type X, and that is OK. But then an overloaded operator*( const X& ) is required to form a third temporary which is their ìproductî. Then the copy constructor (c) is called to create f and fill it from the third temp. As soon as creation of f is over, all three temporaries are destroyed. To make this legal, add the overloaded X operator* (const X& ). (Note that it returns X, an instance of class X, not a reference X& -- a temporary needs to be created in this method, to hold the internal data of the result of the operator*).
It is highly recommended that you try compiling and running small pieces of code that deal with construction of objects and temporaries, passing them as arguments to functions etc. The fraction class code is a good place to start. Try various changes to the code, and observe the results.