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

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


class Screen { public:

заменяет

void operator delete( void * ); void operator delete( void *, size t );

нредонределенн1й тин size t (не забудьте включить заголовочный файл <cstddef>): };

Если второй параметр есть, компилятор автоматически инициализирует его значением, равным размеру адресованного первым параметром объекта в байтах. (Этот параметр важен в иерархии классов, когда оператор delete() может наследоваться производным классом. Подробнее наследование обсуждается в главе 17.)

Рассмотрим реализацию операторов new() и delete() в классе Screen более детально. В основе нашей стратегии распределения памяти будет лежать связанный список объектов Screen, на начало которого указывает член freeStore. При каждом обращении к оператору-члену new() возвращается следующий объект из списка. При вызове delete() объект возвращается в список. Если при создании нового объекта список, адресованный freeStore, пуст, то вызывается глобальный оператор new() , чтобы получить блок памяти, достаточный для хранения screenChunk объектов класса Screen.

Как screenChunk, так и freeStore представляют интерес только для Screen, поэтому мы сделаем их закрытыми членами. Кроме того, для всех создаваемых объектов нашего класса значения этих членов должны быть одинаковыми, а следовательно, нужно объявить их статическими. Чтобы поддержать структуру связанного списка объектов

class Screen {

public:

void *operator new( size t ); void operator delete( void *, size t );

...

private:

Screen *next; static Screen *freeStore; static const int screenChunk;

Screen, нам понадобится третий член next: Вот одна из возможных реализаций оператора new() для класса Screen:

Оператор delete() , определенный для типа класса, может содержать два параметра вместо одного. Первый параметр по-прежнему должен иметь тип void*, а второй -



#include Screen.h

#include <cstddef>

/ / статические члены инициазиртся

в исходн файлах программ!, а не в заголовочн файлах

Screen *Screen::freeStore = 0;

const int Screen::screenChunk = 24;

void *Screen::operator new( size t size ) {

Screen *p;

if ( !freeStore ) {

связанный список пуст: получить новый блок

вызается глобальн оператор new size t chunk = screenChunk * size; freeStore = p =

reinterpret cast< Screen* >( new char[ chunk ] );

вкчить полученн блок в список for ( ;

p != &freeStore[ screenChunk - 1 ];

++p ) p->next = p+1; p->next = 0;

p = freeStore;

freeStore = freeStore->next; return p;

void Screen::operator delete( void *p, size t ) {

вставить удаленный объект назад, в список свободных

( static cast< Screen* >( p ) )->next = freeStore; freeStore = static cast< Screen* >( p );

А вот реализация оператора delete ():

Оператор new() можно объявить в классе и без соответствующего delete() . В таком случае объекты освобождаются с помощью одноименного глобального оператора. Разрешается также объявить и оператор delete () без new(): объекта: будут создаваться с помощью одноименного глобального оператора. Однако обычно эти операторы реализуются одновременно, как в примере выше, поскольку разработчику класса, как правило, нужны оба.

Они являются статическими членами класса, даже если программист явно не объявит их таковыми, и подчиняются обычным ограничениями для подобных функций-членов: им не передается указатель this, а следовательно, напрямую они могут получить доступ только к статическим членам. (См. обсуждение статических функций-членов в разделе 13.5.) Причина, по которой эти операторы делаются статическими, заключается в том,



Псевдокод на C++ ptr = Screen::operator

ptr = Screen::operator new( sizeof( Screen ) );

эквивалентно последовательному выполнению таких инструкций:

Screen::Screen( ptr, 10, 20 );

Иными словами, сначала вызывается определенный в классе оператор new(), чтобы выделить память для объекта, а затем этот объект инициализируется конструктором. Если new() неудачно завершает работу, то возбуждается исключение типа bad alloc и конструктор не вызывается.

Освобождение памяти с помощью оператора delete(), например:

delete ptr;

Псевдокод на C++ Screen::~Screen( ptr );

эквивалентно последовательному выполнению таких инструкций:

Screen::operator delete( ptr, sizeof( *ptr ) );

Таким образом, при уничтожении объекта сначала вызывается деструктор класса, а затем определенный в классе оператор delete() для освобождения памяти. Если значение ptr равно 0, то ни деструктор, ни delete() не вызываются.

15.8.1. Операторы new[ ] и delete [ ]

Оператор new() , определенный в предыдущем подразделе, вызывается только при выделении памяти для единичного объекта. Так, в данной инструкции вызывается new()

вызывается Screen::operator new()

класса Screen:

Screen *ps = new Screen( 24, 80 );

тогда как ниже вызывается глобальный оператор new[]() для выделения из хипа памяти

вызывается Screen::operator new[]() под массив объектов типа Screen:

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

Выделение памяти с помощью оператора new() , например:

Screen *ptr = new Screen( 10, 20 );



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

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