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

1 ... 71 72 73 [ 74 ] 75 76 77 ... 395


class ilist item { public:

ilist item( int value, ilist -item *item to link to = 0 );

inline

ilist item::

ilist item( int value, ilist item *item ) : value( value )

if ( item )

next = 0;

else {

next = item-> next; item-> next = this;

Операция insert() в общем случае работает с двумя параметрами - значением и адресом элемента, после которого производится вставка. Наш первый вариант

inline void

ilist::

insert( ilist item *ptr, int value ) {

new ilist item( value, ptr ); ++ size;

реализации имеет два недочета. Сможете ли вы их найти?

Одна из проблем заключается в том, что указатель не проверяется на нулевое значение. Mi обязаны распознать и обработать такую ситуацию, иначе это приведет к краху программе! во время исполнения. Как реагировать на нулевой указатель? Можно аварийно закончить выполнение, вызвав стандартную функцию abort() , объявленную в

#include <cstdlib>

...

if ( ! ptr )

заголовочном файле cstdlib:

abort() ;

Кроме того, можно использовать макрос assert() . Это также приведет к аварийному

#include <cassert>

...

завершению, но с выводом диагностического сообщения:

assert( ptr != 0 );

Третья возможность - возбудить исключение:



if ( ! ptr )

throw Panic: ilist::insert(): ptr == O ;

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

Если мы не можем продолжать выполнение там, где обнаружена ошибка, лучшим решением будет возбуждение исключения: оно передает управление вызвавшей программе в надежде, что та сумеет выйти из положения.

Мы же поступим совсем другим способом: рассмотрим передачу нулевого указателя как

if ( ! ptr )

запрос на вставку элемента перед первым в списке:

insert front( value );

Второй изъян в нашей версии можно назвать философским. Мы реализовали size() и size как пробный вариант, который может впоследствии измениться. Если мы преобразуем функции size() таким образом, что она будет просто пересчитывать элементы списка, член size перестанет быть нужным. Написав:

++ size;

мы тесно связали реализацию insert() с текущей конструкцией алгоритма пересчета элементов списка. Если мы изменим алгоритм, нам придется переписывать эту функцию, как и insert front() , insert end() и все операции удаления из списка. Вместо того чтобы распространять детали текущей реализации на разные функции класса, лучше

inline void ilist::bump up size() { ++ size; }

инкапсулировать их в паре:

inline void ilist::bump down size() { -- size; }

Поскольку мы объявили эти функции встроенными, эффективность не пострадала. Вот

inline void

ilist::

insert( ilist item *ptr, int value )

if ( !ptr )

insert front( value );

else {

bump up size();

new ilist item( value, ptr );

окончательный вариант insert() :



inline void

ilist::

insert front( int value ) {

ilist item *ptr = new ilist item( value );

if ( ! at front )

at front = at end = ptr; else {

ptr->next( at front ); at front = ptr;

bump up size();

inl-ine void

ilist::

insert end( int value ) {

if ( ! at end )

at end = at front = new ilist item( value ); else at end = new ilist item( value, at end );

bump up s-ize();

из них мы должны предусмотреть случай, когда список пуст.

find() ищет значение в списке. Если элемент с указанным значением найден,

ilist item*

ilist::

find( int value ) {

ilist item *ptr = at front; while ( ptr ) {

if ( ptr->value() == value ) break;

ptr = ptr->next();

return ptr;

возвращается его адрес, иначе find () возвращает 0. Реализация find() выглядит так:

ilist item *ptr = mylist.find( 8 );

Функцию find() можно использовать следующим образом:

mylist.insert( ptr, some value );

или в более компактной записи:

Реализация функций insert front() и insert end() достаточно очевидна. В каждой



1 ... 71 72 73 [ 74 ] 75 76 77 ... 395

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