1
Defining objects may result in some unexpected surprises. Assume the following
2
class interface is available:
9
Data(int one, int two);
15
The intention is to define two objects of the class Data, using, respectively,
16
the first and second constructors. Your code looks like this (and compiles
27
Now it's time to make some good use of the tt(Data) objects. You add two
28
statements to tt(main):
33
But, surprise, the compiler complains about the first of these two:
35
em(error: request for member 'display' in 'd1', which is of non-class type
38
What's going on here? First of all, notice the data type the compiler refers
39
to: tt(Data()), rather than tt(Data). What are those tt(()) doing there?
41
Before answering that question, let's broaden our story somewhat. We know that
42
somewhere in a library a emi(factory function) tt(dataFactory) exists. A
43
factory function creates and returns an object of a certain type. This
44
tt(dataFactory) function returns a tt(Data) object, constructed using
45
tt(Data)'s default constructor. Hence, tt(dataFactory) needs no arguments. We
46
want to use tt(dataFactory) in our program, but must declare the function. So
47
we add the declaration to tt(main), as that's the only location where
48
tt(dataFactory) will be used. It's a function, not requiring arguments,
49
returning a tt(Data) object:
53
This, however, looks remarkably similar to our tt(d1) object definition:
58
We found the source of our problem: tt(Data d1()) apparently is em(not)
59
the definition of a tt(d1) object, but the em(declaration) of a function,
60
returning a tt(Data) object. So, what's happening here and how should we
61
define a tt(Data) object using tt(Data)'s default constructor?
63
First: what's happening here is that the compiler, when confronted with
64
tt(Data d1()), actually had a choice. It could either define a tt(Data)
65
object, or declare a function. It declares a function.
67
In fact, we're encountering an i(ambiguity) in bf(C++)'s syntax here, which is
68
solved, according to the language's standard, by always letting a declaration
69
prevail over a definition. We'll encounter more situations where this
70
ambiguity occurs later on in this section.
72
Second: there are several ways we can solve this ambiguity the way we
73
want it to be solved. To define an object using its default constructor:
75
it() merely mention it (like tt(int x)): tt(Data d1);
76
it() use the curly-brace initialization: tt(Data d1{});
77
it() use the assignment operator and an anonymous default constructed
78
tt(Data) object: tt(Data d1 = Data()).