Программирование >>  Инициализация объектов класса, структура 

1 ... 240 241 242 [ 243 ] 244 245 246 ... 395


Screens ScreenPtr::operator++(int) {

if ( size == 0 ) {

cerr << не могу инкрементировать указатель для одного объекта\n ; return *ptr;

if ( offset == size ) {

cerr << уже на один элемент дальше конца массива\n ; return *ptr;

++offset; return *ptr++;

Screens ScreenPtr::operator--(int) {

if ( size == 0 ) {

cerr << не могу декрементировать указатель для одного объекта\n ; return *ptr;

if ( offset == -1 ) {

cerr << уже на один элемент раньше начала массива\n ; return *ptr;

--offset; return *ptr-- ;

Ниже приведена возможная реализация постфиксных операторов:

Обратите внимание, что давать название второму параметру нет необходимости, поскольку внутри определения оператора он не употребляется. Компилятор сам подставляет для него значение по умолчанию, которое можно игнорировать. Вот пример

const int arrSize = 10; Screen *parray = new Sc

*parray, arrSize

for ( int ix = 0; ix < arrSize; ++ix)

Screen *parray = new Screen[ arrSize ]; ScreenPtr parr( *parray, arrS

использования постфиксного оператора:

printScreen( parr++ );

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

parr.operator++(1024); вызов постфиксного operator++

Перегруженные операторы инкремента и декремента разрешается объявлять как дружественные функции. Изменим соответствующим образом определение класса ScreenPtr:



class ScreenPtr {

объявления не членов

friend Screens operator++( Screen s ); префиксные операторы friend Screens operator-- ( Screen s );

friend Screens operator++( Screen s, int); постфикснхе операторы friend Screens operator-- ( Screen s, int); public:

определения членов

Упражнение 15.7

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

Упражнение 15.8

С помощью ScreenPtr можно представить указатель на массив объектов класса Screen. Модифицируйте перегруженные operator*() и operator->() (см. раздел 15.6) так, чтобы указатель ни при каком условии не адресовал элемент перед началом или за концом массива. Совет: в этих операторах следует воспользоваться новыми членами size и offset.

15.8. Операторы new и delete

По умолчанию выделение объекта класса из хина и освобождение занятой им памяти выполняются с помощью глобальных операторов new() и delete() , определенных в стандартной библиотеке С++. (Mi рассматривали эти операторы в разделе 8.4.) Но класс может реализовать и собственную стратегию управления памятью, предоставив одноименные онераторы-члены. Если они определены в классе, то вызываются вместо глобальных операторов с целью выделения и освобождения памяти для объектов этого класса.

Определим операторы new() и delete() в нашем классе Screen.

Оператор-член new() должен возвращать значение типа void* и принимать в качестве первого параметра значение тина size t, где size t - это typedef, определенный в

class Screen { public:

void *operator new( size t );

системном заголовочном файле <cstddef>. Вот его объявление: };

Когда для создания объекта тина класса используется new(), компилятор проверяет, определен ли в этом классе такой оператор. Если да, то для выделения памяти под объект вызывается именно он, в противном случае - глобальный оператор new() . Например, следующая инструкция

Screen *ps = new Screen;



class Screen {

public:

void operator delete( void * );

для Screen: };

Когда операндом delete служит указатель на объект типа класса, компилятор проверяет, определен ли в этом классе оператор delete() . Если да, то для освобождения памяти вызывается именно он, в противном случае - глобальная версия оператора. Следующая инструкция

delete ps;

освобождает память, занятую объектом класса Screen, на который указывает ps. Поскольку в Screen есть оператор-член delete() , то применяется именно он. Параметр оператора типа void* автоматически инициализируется значением ps.

Добавление delete() в класс или его удаление оттуда никак не сказываются на пользовательском коде. Вызов delete выглядит одинаково как для глобального оператора, так и для оператора-члена. Если бы в классе Screen не было собственного оператора delete() , то обращение осталось бы правильным, только вместо оператора-члена вызывался бы глобальный оператор.

С помощью оператора разрешения глобальной области видимости можно вызвать глобальный delete() , даже если в Screen определена собственная версия:

::delete ps;

В общем случае используемый оператор delete() должен соответствовать тому оператору new() , с помощью которого была выделена память. Например, если ps указывает на область памяти, выделенную глобальным new() , то для ее освобождения следует использовать глобальный же delete() .

создает объект Screen в хипе, а поскольку в этом классе есть оператор new() , то вызывается он. Параметр size t оператора автоматически инициализируется значением, равным размеру Screen в байтах.

Добавление оператора new() в класс или его удаление оттуда не отражаются на пользовательском коде. Вызов new выглядит одинаково как для глобального оператора, так и для оператора-члена. Если бы в классе Screen не было собственного new() , то обращение осталось бы правильным, только вместо оператора-члена вызывался бы глобальный оператор.

С помощью оператора разрешения глобальной области видимости можно вызвать глобальный new() , даже если в классе Screen определена собственная версия:

Screen *ps = ::new Screen;

Оператор delete(), являющийся членом класса, должен иметь тип void, а в качестве первого параметра принимать void*. Вот как выглядит его объявление



1 ... 240 241 242 [ 243 ] 244 245 246 ... 395

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