|
Программирование >> Инициализация объектов класса, структура
class Bear : public ZooAnimal { public: virtual ~Bear(); virtual ostreamS print( ostreamS ) const; virtual string isA() const; ... class Endangered { public: virtual ~Endangered(); virtual ostreamS print( ostreamS ) const; virtual void highlight() const; ... разделе 17.5.) }; Теперь определим в классе Panda собственный экземпляр print() , собственный class Panda : public Bear, public Endangered { public: virtual ~Panda(); virtual ostreamS print( ostreamS ) const; virtual void cuddle(); ... деструктор и еще одну виртуальную функцию cuddle() : }; Множество виртуальных функций, которые можно напрямую вызывать для объекта Panda, представлено в табл. 18.1. Таблица 18.1. Виртуальные функции для класса Panda Имя виртуальной функции Активный экземпляр Компилятор не может различить два непосредственных базовых класса с точки зрения преобразования производного. Равным образом применимы обе трансформации. (Мы покажем способ разрешения этого конфликта в разделе 18.4.) Чтобы понять, какое влияние оказывает множественное наследование на механизм виртуальных функций, определим их набор в каждом из непосредственных базовых классов Panda. (Виртуальные функции введены в разделе 17.2 и подробно обсуждались в
Когда ссылка или указатель на объект Bear или ZooAnimal инициализируется адресом объекта Panda или ему присваивается такой адрес, то части интерфейса, связанные с Bear *pb = new Panda; pb->print( cout ); i6aaeeuii: Panda::print(ostreamS) pb->isA(); i6aaeeuii: Bear::isA() pb->cuddle(); i0eaea: yoi ia +an6u ei6a66aena Bear pb->highlight(); i0eaea: y6i ia +an6u ei6a66aena Bear классами Panda и Endangered, становятся недоступны: delete pb; правильно: Panda::~Panda() (Обратите внимание, что если бы объекту класса Panda был присвоен указатель на ZooAnimal, то все показанные выше вызовы разрешались бы так же.) Аналогично, если ссылка или указатель на объект Endangered инициализируется адресом объекта Panda или ему присваивается такой адрес, то части интерфейса, Endangered *pe = new Panda; pe->print( cout ); правильно: Panda::print(ostreamS) i0eaea: y6i ia +an6u ei6a66aena Endangered pe->cuddle(); pe->highlight(); правильно: Endangered::highlight() связанные с классами Panda и Bear, становятся недоступными: delete pe; правильно: Panda::~Panda() Обработка виртуального деструктора выполняется правильно независимо от типа указателя, через который мы уничтожаем объект. Например, во всех четырех инструкциях порядок вызова деструкторов один и тот же - обратный порядку вызова конструкторов: / / ZooAAnimal *pz = new Panda; delete pz; Bear *pb = new Panda; delete pb; Panda *pp = new Panda; delete pp; Endangered *pe = new Panda; delete pe; Деструктор класса Panda вызывается с помощью механизма виртуализации. После его выполнения по очереди статически вызываются деструкторы Endangered и Bear, а в самом конце - ZooAnimal. Почленная инициализация и присваивание объекту производного класса, наследующего нескольким базовым, ведут себя точно так же, как и при одиночном наследовании (см. class Panda : public Bear, public Endangered раздел 17.6). Например, для нашего объявления класса Panda { ... }; Panda yin yang; в результате почленной инициализации объекта ling ling Panda ling ling = yin yang; вызывается копирующий конструктор класса Bear (но, так как Bear производный от ZooAnimal, сначала выполняется копирующий конструктор класса ZooAnimal), затем -класса Endangered и только потом - класса Panda. Почленное присваивание ведет себя аналогично. Упражнение 18.1 Какие из следующих объявлений ошибочны? Почему? (b) class DoublyLinkedList: (a) class CADVehicle : public CAD, Vehicle { ... }; public List, public List { ... };
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |