Язык программирования C++



             

Инициализация объектов - часть 3


class Repository { . . . }; class Item { public: Item(Repository& rep) : myRepository(rep) {}; . . . private: Repository& myRepository; };

При создании объекта необходимо указать, где он хранится. Изменить хранилище нельзя, пока данный объект не уничтожен. Атрибут myRepository всегда ссылается на один и тот же объект.

Второй вариант заключается в том, что книги можно перемещать из одного хранилища в другое. Тогда в качестве атрибута класса Item лучше использовать указатель на Repository:

class Item { public: Item() : myRepository(0) {}; Item(Repository* rep) : myRepository(rep) {}; void MoveItem(Repository* newRep); . . . private: Repository* myRepository; };

Создавая объект Item, можно указать, где он хранится, а можно и не указывать. Впоследствии можно изменить хранилище, например с помощью метода MoveItem.

При уничтожении объекта вызов деструкторов происходит в обратном порядке. Вначале вызывается деструктор самого класса, затем деструкторы атрибутов этого класса и, наконец, деструктор базового класса.

В создании и уничтожении объектов имеется одно существенное отличие. Создавая объект, мы всегда точно знаем, какому классу он принадлежит. При уничтожении это не всегда известно.

Item* itptr; if (type == "book") itptr = new Book(); else itptr = new Magazin(); . . . delete itptr;

Во время компиляции неизвестно, каким будет значение переменной type и, соответственно, объект какого класса удаляется операцией delete. Поэтому компилятор может вставить вызов только деструктора базового класса.

Для того чтобы все необходимые деструкторы были вызваны, нужно воспользоваться виртуальным механизмом – объявить деструктор как в базовом классе, так и в производном, как virtual.

class Item { virtual ~Item(); }; class Book { public: virtual ~Book(); };

Возникает вопрос – почему бы всегда не объявлять деструкторы виртуальными? Единственная плата за это – небольшое увеличение памяти для реализации виртуального механизма. Таким образом, не объявлять деструктор виртуальным имеет смысл только в том случае, если во всей иерархии классов нет виртуальных функций, и удаление объекта никогда не происходит через указатель на базовый класс.




Содержание  Назад  Вперед