Under single inheritance, a pointer or a reference to a derived class can be converted automatically to a pointer or a reference to an accessible base class (§ 15.2.2, p. 597, and § 15.5, p. 613). The same holds true with multiple inheritance. A pointer or reference to any of an object’s (accessible) base classes can be used to point or refer to a derived object. For example, a pointer or reference to ZooAnimal
, Bear
, or Endangered
can be bound to a Panda
object:
// operations that take references to base classes of type Panda
void print(const Bear&);
void highlight(const Endangered&);
ostream& operator<<(ostream&, const ZooAnimal&);
Panda ying_yang("ying_yang");
print(ying_yang); // passes Panda to a reference to Bear
highlight(ying_yang); // passes Panda to a reference to Endangered
cout << ying_yang << endl; // passes Panda to a reference to ZooAnimal
Exercise 18.21: Explain the following declarations. Identify any that are in error and explain why they are incorrect:
(a) class CADVehicle : public CAD, Vehicle { ... };
(b) class DblList: public List, public List { ... };
(c) class iostream: public istream, public ostream { ... };
Exercise 18.22: Given the following class hierarchy, in which each class defines a default constructor:
class A { ... };
class B : public A { ... };
class C : public B { ... };
class X { ... };
class Y { ... };
class Z : public X, public Y { ... };
class MI : public C, public Z { ... };
what is the order of constructor execution for the following definition?
MI mi;
The compiler makes no attempt to distinguish between base classes in terms of a derived-class conversion. Converting to each base class is equally good. For example, if there was an overloaded version of print
:
void print(const Bear&);
void print(const Endangered&);
an unqualified call to print
with a Panda
object would be a compile-time error:
Panda ying_yang("ying_yang");
print(ying_yang); // error: ambiguous
As with single inheritance, the static type of the object, pointer, or reference determines which members we can use (§ 15.6, p. 617). If we use a ZooAnimal
pointer, only the operations defined in that class are usable. The Bear
-specific, Panda-
specific, and Endangered
portions of the Panda
interface are invisible. Similarly, a Bear
pointer or reference knows only about the Bear
and ZooAnimal
members; an Endangered
pointer or reference is limited to the Endangered
members.
As an example, consider the following calls, which assume that our classes define the virtual functions listed in Table 18.1:
Bear *pb = new Panda("ying_yang");
pb->print(); // ok: Panda::print()
pb->cuddle(); // error: not part of the Bear interface
pb->highlight(); // error: not part of the Bear interface
delete pb; // ok: Panda::~Panda()
When a Panda
is used via an Endangered
pointer or reference, the Panda-
specific and Bear
portions of the Panda
interface are invisible:
Endangered *pe = new Panda("ying_yang");
pe->print(); // ok: Panda::print()
pe->toes(); // error: not part of the Endangered interface
pe->cuddle(); // error: not part of the Endangered interface
pe->highlight(); // ok: Panda::highlight()
delete pe; // ok: Panda::~Panda()