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
|
Let's investigate closer why an tt(AirCar) introduces i(ambiguity), when
derived from tt(Car) and tt(Air).
itemization(
it() An tt(AirCar) is a tt(Car), hence a tt(Land), and hence a
tt(Vehicle).
it() However, an tt(AirCar) is also an tt(Air), and hence a tt(Vehicle).
)
The duplication of tt(Vehicle) data is further illustrated in
fig(ambiguity).
figure(polymorphism/ambiguity)
(Duplication of a base class in multiple derivation.)
(ambiguity)
The internal organization of an tt(AirCar) is shown in
fig(InternalOrganization)
figure(polymorphism/internal)
(Internal organization of an tt(AirCar) object.)
(InternalOrganization)
The bf(C++) compiler detects the ambiguity in an tt(AirCar) object,
and will therefore not compile statements like:
verb( AirCar jBond;
cout << jBond.mass() << '\n';)
Which member function tt(mass) to call cannot be determined by the
compiler but the programmer has two possibilities to resolve the ambiguity for
the compiler:
itemization(
it() First, the function call where the ambiguity originates can be
modified. The ambiguity is resolved using the i(scope resolution operator):
verb(// let's hope that the mass is kept in the Car
// part of the object..
cout << jBond.Car::mass() << '\n';)
The scope resolution operator and the class name are put right before
the name of the member function.
it() Second, a dedicated function tt(mass) could be created for
the class tt(AirCar):
verb(int AirCar::mass() const
{
return Car::mass();
})
)
The second possibility is preferred as it does not require the compiler to
flag an error; nor does it require the programmer using the class
tt(AirCar) to take special precautions.
However, there exists a more elegant solution, discussed in the next
section.
|