|
Программирование >> Программирование на языке c++
независимо от атрибута базового класса все его компоненты private недоступны за пределами базового класса; атрибут public базового класса не изменяет атрибуты public и protected для его компонентов в производном классе; атрибут protected базового класса изменяет атрибут public его компонентов на атрибут protected в производном классе; атрибут private базового класса изменяет атрибуты public и protected его компонентов на атрибут private в производном классе; если базовый класс имеет атрибут private, то невозможно получить доступ к его компонентам из-за пределов производного класса (т. е. через имя, ссылку или указатель на производный класс); атрибут компонента базового класса в производном классе можно изменить, задав полное имя этого компонента в public или protected секции производного класса, например: struct X { int х; }; class Y : private X { в классе Y х имеет атрибут private public: Х::х; private х становится public х ............. }; 4.7. Виртуальные деструкторы Выше уже говорилось, что в языке С++ деструктор может быть виртуальным, а конструктор нет. Рассмотрим пример [1], который показывает полезность использования виртуальных деструкторов. В языке С++ есть два оператора - new (для динамического выделения памяти) и delete (для освобождения динамически вьщеленной ранее памяти). Большинство операторов языка С++ можно снабдить дополнительными функциями. Этот процесс называется operator overloading, подробно он рассматривается в следующей главе. Функции, выполняемые операторами new и delete, тоже можно расширить или изменить. Рассмотрим следующую задачу. Заданы базовый и некоторые производные классы. Необходимо использовать операторы new и delete для выделения и освобождения памяти под объект базового класса или объект любого производного класса. В этом случае базовый класс Б может содержать специальный выделитель памяти для Б и для любого класса П (Б<-П), например: class book { public: void* operator new(size t); void operator delete(void*, size t); void book::operator new(size t real size) { выделение real size байт памяти и возвращение указателя на начало этой памяти void book::operator delete(void* pointer,size t real size) { pointer - это указатель на начало памяти, которую необходимо освободить (значение этого указателя было возвращено оператором new), real size - размер памяти, которую надо освободить. Оператор delete должен освобождать указанную память Здесь size t - это тип (например, unsigned) и real size - размер памяти, которую надо либо выделить, либо освободить. Если необходимо удалить объект типа boolc, то размер этого объекта можно вычислить с помощью оператора sizeof(bool{). Если нужно удалить объект класса programmers guide, то размер объекта вычисляется аналогичным образом, т. е. sizeof(programmers guide). Это позволяет не запоминать в переменных объем выделенной памяти, когда оператор new применяется к конкретному объекту (поскольку этот объем легко вычисляется). Таким образом, оператор delete может не иметь аргументов, однако в этом случае мы должны объявить виртуальный деструктор в нашем базовом классе. Продолжим рассмотрение примера: class programmers guide : public book { ............................}; void main(void) { book* pointer = new programmers guide; delete pointer; } Здесь возникает ошибка, поскольку компилятор не знает о действительном размере удаляемого объекта. Ранее говорилось, что деструктор вызывается всегда при разрушении объекта. В нашем случае объект разрушается с помощью оператора delete pointer; При этом будет вызван деструктор базового класса, а он не знает о размере производного объекта progranimers guide (см. прил. 2.2). Виртуальный деструктор можно добавить следующим образом: class book { public: void* operator new(size t); void operator delete(void*,size t); virtual ~book(void); Это приведет к тому, что будет вызван деструктор того объекта, на который указывает pointer (в приведенном выше примере - это объект programmers guide), и он знает о размере объекта. Теперь любой класс, который наследуется из класса book, должен иметь свой деструктор. Пользователь не должен вызывать этот деструктор, однако рассмотренная выше функция void main(void) { book* pointer = new programmers guide; delete pointer; } теперь будет работать правильно, поскольку при выделении памяти компилятор вызовет функцию:
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |