|
Программирование >> Инициализация объектов класса, структура
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 );
|
© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |