Rules for Declaring Constructors

A constructor has the same name as its class. Any number of constructors can be declared, subject to the rules of overloaded functions. (For more information, see Chapter 12, “Overloading.”)

Syntax

class-name(argument-declaration-listopt)cv-mod-listopt

C++ defines two special kinds of constructors, default and copy constructors, described in Table 11.2.

Table 11.2 Default and Copy Constructors

Kind of Construction Arguments Purpose

Default constructor Can be called with no arguments Construct a default object of the class type
Copy constructor Can accept a single argument of reference to same class type Copy objects of the class type

Default constructors can be called with no arguments. However, you can declare a default constructor with an argument list, provided all arguments have defaults. Similarly, copy constructors must be declared such that they can accept a single argument of reference to the same class type. More arguments can be supplied, provided all subsequent arguments have defaults.

If you do not supply any constructors, the compiler attempts to generate a default constructor. If you do not supply a copy constructor, the compiler attempts to generate one. These compiler-generated constructors are considered public member functions. Specifying a copy constructor with a first argument that is an object, and not a reference, generates an error.

A compiler-generated default constructor sets up the object (initializes vftables, and vbtables, as described previously), and it calls the default constructors for base classes and members, but it takes no other action. Base class and member constructors are called only if they exist, if they are accessible, and if they are unambiguous.

A compiler-generated copy constructor sets up a new object and performs a memberwise copy of the contents of the object to be copied. If base class or member constructors exist, they are called; otherwise, bitwise copying is performed.

If all base and member classes of a class type have copy constructors that accept a const argument, the compiler-generated copy constructor accepts a single argument of type const type&. Otherwise, the compiler-generated copy constructor accepts a single argument of type type&.

You can use a constructor to initialize a const or volatile object, but the constructor itself cannot be declared as either const or volatile. In addition, constructors cannot be declared as virtual or static.

Constructors of base classes are not inherited by derived classes. When an object of derived class type is created, it is constructed starting with the base class components; then it moves to the derived class components. The compiler uses each base class's constructor as that part of the complete object is initialized (except in cases of virtual derivation, as described in “Initializing Base Classes”).

Explicitly Called Constructors

Constructors can be explicitly called in a program to create objects of a given type. For example, to create two Point objects that describe the ends of a line, the following code can be written:

DrawLine( Point( 13, 22 ), Point( 87, 91 ) );

Two objects of type Point are created, passed to the function DrawLine, and destroyed at the end of the expression (the function call).

Another context in which a constructor is explicitly called is in an initialization:

Point pt = Point( 7, 11 );

An object of type Point is created and initialized using the constructor that accepts two arguments of type int.

Objects that are created by calling constructors explicitly, as in the preceding two examples, are unnamed and have a lifetime of the expression in which they are created. This is discussed in greater detail in “Temporary Objects”.

Calling Member Functions and Virtual Functions from Within Constructors

Because the object has been completely set up (virtual tables have been initialized and so on) prior to the execution of the first line of user code, it is usually safe to call any member function from within a constructor. A potentially unsafe member function call has to do with calling a virtual member function for an abstract base class during construction or destruction.

Constructors can call virtual functions. When virtual functions are called, the function invoked is the function defined for the constructor's own class (or inherited from its bases). The following example shows what happens when a virtual function is called from within a constructor:

#include <iostream.h>

class Base

{

Base(); // Default constructor.

virtual void f(); // Virtual member function.

};

Base::Base()

{

cout << "Constructing Base sub-object\n";

f(); // Call virtual member function

} // from inside constructor.

void Base::f()

{

cout << "Called Base::f()\n";

}

class Derived : public Base

{

Derived(); // Default constructor.

void f(); // Implementation of virtual

}; // function f for this class.

Derived::Derived()

{

cout << "Constructing Derived object\n";

}

void Derived::f()

{

cout << "Called Derived::f()\n";

}

void main()

{

Derived d;

}

When the preceding program is run, the declaration Derived d causes the following sequence of events to occur:

1.The constructor for class Derived (Derived::Derived) is called.

2.Prior to entering the body of the Derived class's constructor, the constructor for class Base (Base::Base) is called.

3.Base::Base calls the function f, which is a virtual function. Ordinarily, Derived::f would be called because the object d is of type Derived. Because the Base::Base function is a constructor, the object is not yet of the Derived type, and Base::f is called.