Программирование >>  Программирование на языке c++ 

1 ... 54 55 56 [ 57 ] 58 59 60 ... 159


независимо от атрибута базового класса все его компоненты 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; }

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



1 ... 54 55 56 [ 57 ] 58 59 60 ... 159

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика