File: base.yo

package info (click to toggle)
c%2B%2B-annotations 8.2.0-1
  • links: PTS
  • area: main
  • in suites: squeeze
  • size: 11,804 kB
  • ctags: 2,845
  • sloc: cpp: 15,418; makefile: 2,473; ansic: 165; perl: 90; sh: 29
file content (190 lines) | stat: -rw-r--r-- 7,621 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
    As illustrated in fig(InternalOrganization), an tt(AirAuto) represents
em(two) tt(Vehicle)s. This not only results in an i(ambiguity) about which
function to use to access the tt(mass) data, but it also defines two
tt(mass) fields in an tt(AirAuto). This is slightly redundant, since we can
assume that an tt(AirAuto) has but one mass.

    It is, however, possible to define an tt(AirAuto) as a class consisting of
but one tt(Vehicle) and yet using multiple derivation.  This is realized by
defining the base classes that are multiply mentioned in a derived class's
inheritance tree as a
 hi(base class: virtual) emi(virtual base class).

    For the class tt(AirAuto) this implies a small change when deriving an
tt(AirAuto) from tt(Land) and tt(Air) classes:
        verb(
    class Land: virtual public Vehicle
    {
        // etc
    };
    class Auto: public Land
    {
        // etc
    };
    class Air: virtual public Vehicle
    {
        // etc
    };
    class AirAuto: public Auto, public Air
    {
    };
        )
    Virtual derivation hi(virtual derivation) ensures that a tt(Vehicle) is
only added once to a derived class. This means that the route along which a
tt(Vehicle) is added to an tt(AirAuto) is no longer depending on its direct
base classes; we can only state that an tt(AirAuto) is a tt(Vehicle).  The
internal organization of an tt(AirAuto) after virtual derivation is shown in
fig(VirtualBaseClass).
    figure(polymorphism/virtbase)
        (Internal organization of an tt(AirAuto) object when the base
            classes are virtual.)
        (VirtualBaseClass)

    When a class tt(Third) inherits from a base class tt(Second) which in turn
inherits from a base class tt(First) then the tt(First) class constructor
called by the tt(Second) class constructor is also used when this tt(Second)
constructor is used when constructing a tt(Third) object. Example:
        verb(
    class First
    {
        public:
            First(int x);
    };
    class Second: public First
    {
        public:
            Second(int x)
            :
                First(x)
            {}
    };
    class Third: public Second
    {
        public:
            Third(int x)
            :
                Second(x)           // calls First(x)
            {}
    };
        )
    The above no longer holds true when tt(Second) uses virtual derivation.
When tt(Second) uses virtual derivation its base class constructor is
em(ignored) when tt(Second)'s constructor is called from tt(Third). Instead
tt(Second) will by default call tt(First)'s default constructor. This is
illustrated by the next example:
        verbinsert(CLASSES)(polymorphism/examples/virtualinherit.cc)
    When constructing tt(Third) tt(First)'s default constructor is used by
default. tt(Third)'s constructor, however, may overrule this default behavior
by explicitly specifying the constructor to use. Since the tt(First) object
must be available before tt(Second) can be constructed it must be specified
first. To call tt(First(int)) when constructing tt(Third(int)) the latter
constructor can be defined as follows:
        verb(
    class Third: public Second
    {
        public:
            Third(int x)
            :
                First(x),           // now First(int) is called.
                Second(x)
            {}
    };
        )
    This behavior may seem puzzling when simple linear inheritance is used but
it makes sense when multiple inheritance is used with base classes using
virtual inheritance. Consider tt(AirAuto): when tt(Air) and tt(Auto) both
virtually inherit from tt(Vehile) will tt(Air) and (Auto) both initialize the
common tt(Vehicle) object? If so, which one will be called first? What if
tt(Air) and tt(Auto) use different tt(Vehicle) constructors? All these
questions can be avoided by passing the responsibility for the initialization
of a common base class to the class eventually using the common base class
object. In the above example tt(Third). Hence tt(Third) is provided an
opportunity to specify the constructor to use when initializing tt(First).

Multiple inheritance may also used to inherit from classes that do not all use
virtual inheritance. Assume we have two classes, tt(Derived1)
and tt(Derived2), both (possibly virtually) derived from tt(Base).

We will address the question which constructors will be called when calling a
constructor of the class tt(Final: public Derived1, public Derived2).

To distinguish the involved constructors tt(Base1) indicates the tt(Base)
class constructor called as base class initializer for tt(Derived1) (and
analogously: tt(Base2) called from tt(Derived2)). A plain tt(Base)  indicates
tt(Base)'s  default constructor.

tt(Derived1) and tt(Derived2) indicate the base class initializers used when
constructing a tt(Final) object.

Now we're ready to distinguish the various cases when constructing an object
of the class tt(Final: public Derived1, public Derived2):
        itemization(
        it() classes:
                verb(
                    Derived1: public Base
                    Derived2: public Base
                )
            quote(This is normal, non virtual multiple derivation. The
                following constructors are called in the order shown:
                verb(
                    Base1,
                    Derived1,
                    Base2,
                    Derived2
                )
            )
        it() classes:
                verb(
                    Derived1: public Base
                    Derived2: virtual public Base
                )
            quote(Only tt(Derived2) uses virtual derivation.
                tt(Derived2)'s base class constructor is ignored.  Instead,
                tt(Base) will be called and it will be called prior to any
                other constructor:
                verb(
                    Base,
                    Base1,
                    Derived1,
                    Derived2
                )
                As only one class uses
                virtual derivation, there will still be em(two) tt(Base) class
                objects in the eventual tt(Final) class.
            )
        it() classes:
                verb(
                    Derived1: virtual public Base
                    Derived2: public Base
                )
            quote(Only tt(Derived1) uses virtual derivation.
                tt(Derived1)'s base class constructor is ignored.  Instead,
                tt(Base) will be called and it will be called prior to any
                other constructor. Different from the first (non-virtual) case
                tt(Base) is now called, rather than tt(Base1):
                verb(
                    Base,
                    Derived1,
                    Base2,
                    Derived2
                )
            )
        it() classes:
                verb(
                    Derived1: virtual public Base
                    Derived2: virtual public Base
                )
            quote(Both base classes use virtual derivation and so
                only em(one) tt(Base) class object will be present in the
                tt(Final) class object. The following constructors are called
                in the order shown:
                verb(
                    Base,
                    Derived1,
                    Derived2
                )
            )
        )
    Virtual derivation is, in contrast to virtual functions, a pure
i(compile-time) issue. Virtual inheritance merely defines
how the compiler defines a class's data organization and construction process.