7.5.3. The Role of the Default Constructor

Image

The default constructor is used automatically whenever an object is default or value initialized. Default initialization happens

• When we define nonstatic variables (§ 2.2.1, p. 43) or arrays (§3.5.1, p. 114) at block scope without initializers

• When a class that itself has members of class type uses the synthesized default constructor (§ 7.1.4, p. 262)

• When members of class type are not explicitly initialized in a constructor initializer list (§ 7.1.4, p. 265)

Value initialization happens

• During array initialization when we provide fewer initializers than the size of the array (§ 3.5.1, p. 114)

• When we define a local static object without an initializer (§ 6.1.1, p. 205)

• When we explicitly request value initialization by writing an expressions of the form T() where T is the name of a type (The vector constructor that takes a single argument to specify the vector’s size (§ 3.3.1, p. 98) uses an argument of this kind to value initialize its element initializer.)

Classes must have a default constructor in order to be used in these contexts. Most of these contexts should be fairly obvious.

What may be less obvious is the impact on classes that have data members that do not have a default constructor:

class NoDefault {
public:
    NoDefault(const std::string&);
    // additional members follow, but no other constructors
};
struct A {  // my_mem is public by default; see § 7.2 (p. 268)
    NoDefault my_mem;
};
A a;       //  error: cannot synthesize a constructor for A
struct B {
    B() {} //  error: no initializer for b_member
    NoDefault b_member;
};


Image Best Practices

In practice, it is almost always right to provide a default constructor if other constructors are being defined.


Using the Default Constructor

The following declaration of obj compiles without complaint. However, when we try to use obj

Sales_data obj();   // ok: but defines a function, not an object
if (obj.isbn() == Primer_5th_ed.isbn())  // error: obj is a function

the compiler complains that we cannot apply member access notation to a function. The problem is that, although we intended to declare a default-initialized object, obj actually declares a function taking no parameters and returning an object of type Sales_data.

The correct way to define an object that uses the default constructor for initialization is to leave off the trailing, empty parentheses:

// ok: obj is a default-initialized object
Sales_data obj;


Image Warning

It is a common mistake among programmers new to C++ to try to declare an object initialized with the default constructor as follows:

Sales_data obj(); // oops! declares a function, not an object
Sales_data obj2;  // ok: obj2 is an object, not a function



Exercises Section 7.5.3

Exercise 7.43: Assume we have a class named NoDefault that has a constructor that takes an int, but has no default constructor. Define a class C that has a member of type NoDefault. Define the default constructor for C.

Exercise 7.44: Is the following declaration legal? If not, why not?

vector<NoDefault> vec(10);

Exercise 7.45: What if we defined the vector in the previous execercise to hold objects of type C?

Exercise 7.46: Which, if any, of the following statements are untrue? Why?

(a) A class must provide at least one constructor.

(b) A default constructor is a constructor with an empty parameter list.

(c) If there are no meaningful default values for a class, the class should not provide a default constructor.

(d) If a class does not define a default constructor, the compiler generates one that initializes each data member to the default value of its associated type.


..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset