~ubuntu-branches/ubuntu/trusty/c++-annotations/trusty-proposed

« back to all changes in this revision

Viewing changes to yo/classes/ambiguity.yo

  • Committer: Package Import Robot
  • Author(s): Frank B. Brokken
  • Date: 2013-05-30 13:32:18 UTC
  • mfrom: (1.1.24)
  • Revision ID: package-import@ubuntu.com-20130530133218-k39mr5uredd093jr
Tags: 9.7.2-1
New upstream release, repairs several minor left-over flaws.
This release incorporates 9.7.0 and 9.7.1.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
Defining objects may result in some unexpected surprises. Assume the following
 
2
class interface is available:
 
3
        verb(
 
4
    class Data
 
5
    {
 
6
        public:
 
7
            Data();
 
8
            Data(int one);
 
9
            Data(int one, int two);
 
10
 
 
11
            void display();
 
12
    };
 
13
        )
 
14
 
 
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
 
17
correctly):
 
18
        verb(
 
19
    #include "data.h"
 
20
    int main()
 
21
    {
 
22
        Data d1();
 
23
        Data d2(argc);
 
24
    }
 
25
        )
 
26
 
 
27
Now it's time to make some good use of the tt(Data) objects. You add two
 
28
statements to tt(main):
 
29
            verb(
 
30
        d1.display();
 
31
        d2.display();
 
32
            )
 
33
    But, surprise, the compiler complains about the first of these two:
 
34
 
 
35
em(error: request for member 'display' in 'd1', which is of non-class type
 
36
'Data()')
 
37
 
 
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?
 
40
 
 
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:
 
50
            verb(
 
51
        Data dataFactory();
 
52
            )
 
53
    This, however, looks remarkably similar to our tt(d1) object definition:
 
54
            verb(
 
55
        Data d1();
 
56
            )
 
57
    
 
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?
 
62
 
 
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. 
 
66
 
 
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.
 
71
 
 
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:
 
74
    itemization(
 
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()).
 
79
    )