// Endangered *pe = new Panda;

delete pe;

Деструктор класса Panda вызывается с помощью механизма виртуализации. После его выполнения по очереди статически вызываются деструкторы Endangered и Bear, а в самом конце – ZooAnimal.

Почленная инициализация и присваивание объекту производного класса, наследующего нескольким базовым, ведут себя точно так же, как и при одиночном наследовании (см. раздел 17.6). Например, для нашего объявления класса Panda

class Panda : public Bear, public Endangered

{ ... };

в результате почленной инициализации объекта ling_ling

Panda yin_yang;

Panda ling_ling = yin_yang;

вызывается копирующий конструктор класса Bear (но, так как Bear производный от ZooAnimal, сначала выполняется копирующий конструктор класса ZooAnimal), затем – класса Endangered и только потом – класса Panda. Почленное присваивание ведет себя аналогично.

Упражнение 18.1

Какие из следующих объявлений ошибочны? Почему?

(a) class CADVehicle : public CAD, Vehicle { ... };

(b) class DoublyLinkedList:

public List, public List { ... };

(c) class iostream:

private istream, private ostream { ... };

Упражнение 18.2

Дана иерархия, в каждом классе которой определен конструктор по умолчанию:

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 { ... };

Каков порядок вызова конструкторов в таком определении:

MI mi;

Упражнение 18.3

Дана иерархия, в каждом классе которой определен конструктор по умолчанию:

class X { ... };

class A { ... };

class B : public A { ... };

class C : private B { ... };

class D : public X, public C { ... };

Какие из следующих преобразований недопустимы:

D *pd = new D;

(a) X *px = pd; (c) B *pb = pd;

(b) A *pa = pd; (d) C *pc = pd;

Упражнение 18.4

Дана иерархия классов, обладающая приведенным ниже набором виртуальных функций:

class Base {

public:

virtual ~Base();

virtual ostream& print();

virtual void debug();

virtual void readOn();

virtual void writeOn();

// ...

};

class Derived1 : virtual public Base {

public:

virtual ~Derived1();

virtual void writeOn();

// ...

};

class Derived2 : virtual public Base {

public:

virtual ~Derived2();

virtual void readOn();

// ...

};

class MI : public Derived1, public Derived2 {

public:

virtual ~MI();

virtual ostream& print();

virtual void debug();

// ...

};

Какой экземпляр виртуальной функции вызывается в каждом из следующих случаев:

Base *pb = new MI;

(a) pb-print(); (c) pb-readOn(); (e) pb-log();

(b) pb-debug(); (d) pb-writeOn(); (f) delete pb;

Упражнение 18.5

На примере иерархии классов из упражнения 18.4 определите, какие виртуальные функции активны при вызове через pd1 и pd2:

(a) Derived1 *pd1 new MI;

(b) MI obj;

Derived2 d2 = obj;

<p>18.3. Открытое, закрытое и защищенное наследование</p>
Перейти на страницу:

Похожие книги