|
Программирование >> Инициализация объектов класса, структура
ilist::ilist( const ilist &rhs ) ilist item *pt = rhs. at front; while ( pt insert end( pt->value() ); pt = pt->next(); реализация конструктора, использующая функцию insert end() : Оператор присваивания должен сначала вызвать remove all(), а затем с помощью insert end() вставить все элементы второго списка. Поскольку эта операция void ilist::insert all ( const ilist &rhs ) ilist item *pt = rhs. at front; while ( pt insert end( pt->value() ); pt = pt->next(); повторяется в обеих функциях, вынесем ее в отдельную функцию insert all() : inline ilist::ilist( const ilist &rhs ) : at front( 0 ), at end( 0 ) { insert all ( rhs ); } inline ilist& ilist::operator=( const ilist &rhs ) { remove all(); insert all( rhs ); return *this; после чего копирующий конструктор и оператор присваивания можно реализовать так: Теперь осталось обеспечить пользователя возможностью путешествовать но списку, например с помощью доступа к члену at front: ilist item *ilist::front() { return at front(); } После этого можно применить ilist item::next() , как мы делали в функциях-членах: запретили его использование. Лучше уж полностью лишить пользователя какой-либо операции, чем допустить возможные ошибки. (В разделе 14.5 объясняется, почему действия копирующего конструктора по умолчанию в подобных случаях неверны.) Вот ilist item *pt = mylist.front(); while ( pt ) { do something( pt->value () ); pt = pt->next(); Хотя это решает проблему, лучше поступить иначе: реализовать общую концепцию прохода по элементам контейнера. В данном разделе м1 расскажем об использовании for ( ilist item *iter = mylist.init iter(); iter; iter = mylist.next iter() ) цикла такого вида: do something( iter->value() ); (В разделе 2.8 м1 уже касались понятия итератора. В главах 6 и 12 будут рассмотрены итераторы для имеющихся в стандартной библиотеке контейнерных типов и обобщенных алгоритмов.) Наш итератор представляет собой несколько больше, чем просто указатель. Он должен уметь запоминать текущий элемент, возвращать следующий и определять, когда все элементы кончились. По умолчанию итератор инициализируется значением at front, однако пользователь может задать в качестве начального любой элемент списка. next iter() возвращает следующий элемент или 0, если элементов больше нет. Для class ilist { public: ... init iter( ilist item *it = 0 ); private: ... ilist item * current; реализации пришлось ввести дополнительный член класса: inline ilist item* ilist::init iter( i1ist item *it ) { return current = it ? it : at front; init iter() выглядит так: next iter() перемещает указатель current на следующий элемент и возвращает его адрес, если элементы не кончились. В противном случае он возвращает 0 и устанавливает current в 0. Его реализацию можно представить следующим образом: inline ilist item* ilist:: next iter() ilist item *next = current return next; ? current = current->next() : current; Если элемент, на котор1й указывает current, удален, могут возникнуть проблем:. Их преодолевают модификацией кода функций remove() и remove front() : они должны проверять значение current. Если он указывает на удаляемый элемент, функции изменят его так, чтобы он адресовал следующий элемент либо был равен 0, когда удаляем1й элемент - последний в списке или список стал пустым. Модифицированная inline void ilist::remove front() if ( at front ) { ilist item *ptr = at front; at front = at front->next(); current не доен указывать на удаленн элемент if ( current == ptr ) current = at front; bump down size(); delete ptr; remove front() выглядит так: while ( plist ) { if ( plist->va if ( plist->value() == value ) prev->next( plist->next() ); if ( current == plist ) Вот модифицированный фрагмент кода remove() : current = prev->next(); Что произойдет, если элемент будет вставлен перед тем, на который указывает current? Значение current не изменяется. Пользователь должен начать проход но списку с помощью вызова init iter() , чтобы новый элемент попал в число перебираемых. При инициализации списка другим и при присваивании значение current не копируется, а сбрасывается в 0. Тестовая программа для проверки работы копирующего конструктора и оператора присваивания выглядит так::
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |