C++: библиотека программиста



Download 1,95 Mb.
Pdf ko'rish
bet69/144
Sana24.02.2022
Hajmi1,95 Mb.
#223123
TuriРеферат
1   ...   65   66   67   68   69   70   71   72   ...   144
Bog'liq
C -Eldjer-Djeff-for-Real-Programmers-RUS-www.itlibitum.ru

 
115 
Foo* foo = array[Index(17, 29)]; 
// Работает 
С чтением массива проблем нет. Если индекс существует, возвращается содержимое массива по 
данному индексу. Если индекс в массиве отсутствует, значение 
NULL
полностью соответствует идее 
предварительной инициализации массива значениями 
NULL
. Минутку, но как добавить в массив новую 
ячейку или изменить уже существующую? Значение, возвращаемое операторной функцией 
operator[]
, не является ни левосторонним выражением (lvalue), ни классом с перегруженным 
оператором 
=
и по нему нельзя выполнить присваивание. 
array[Index(31, 37)] = foo; // Не работает 
Ваш компилятор не спит ночами и ждет, когда же у него появится такая замечательная возможность 
забить поток 
сеrr
сообщениями об ошибках. Можно было бы создать интерфейс на базе функций, но 
тогда у клиента нарушится иллюзия того, что он имеет дело с нормальным, честным массивом. 
Существует ли способ использовать оператор 
[]
в левой части операции присваивания для индексов, 
которых еще нет? Оказывается, существует, но для этой цели нам потребуется новая идиома — курсор. 
Курсоры и разреженные массивы 
Итак, вторая попытка. Наша основная цель — чтобы операторная функция 
operator[]
возвращала 
нечто, обладающее следующими свойствами: 
1. Оно должно преобразовываться к типу содержимого массива. 
2. Оно может использоваться в левой части операции присваивания для изменения содержимого 
соответствующей ячейки. 
Это «нечто» представляет собой особый класс, который называется курсором (cursor). Ниже показан 
уже знакомый разреженный массив с курсором в операторной функции 
operator[]

class ArrayCursor; 
class SparseArray { 
friend class ArrayCursor; 
private: 
struct Node { 
Index 
index; 
Foo* 
content; 
Node* 
next; 
Node(Index i, Foo* c, Node* n) : index(i), content(c), next(n) {}; 
}; 
Node* 
cells; 
public: 
SparseArray() : cells(NULL) {} 
ArrayCursor operator[](Index i); 
}; 
class ArrayCursor { 
friend class SparseArray; 
private: 
SparseArray& 
array;
// 
Обратный указатель на массив-владелец 
Index 
index; 
// 
Элемент, представленный курсором 
SparseArray::Node* 
node; 
// 
Если существует индекс, отличный от NULL 
// 
Конструкторы объявлены закрытыми, поэтому пользоваться ими 
// 
может только SparseArray. Первый конструктор используется, когда 
// 
индекс еще не существует, а второй – когда индекс уже присутствует 
// 
в массиве. 


 116 
ArrayCursor(SparseArray& arr, Index i) 
: array(arr), index(i), node(NULL) {} 
ArrayCursor(SparseArray& arr, SparseArray::Node* n) 
: array(arr), node(n), index(n->index) {} 
public: 
// 
Следующий оператор = позволяет преобразовать присваивание курсору в 
// 
присваивание соответствующему элементу массива. 
ArrayCursor& operator=(Foo* foo); 
}; 
ArrayCursor& ArrayCursor::operator=(Foo* foo) { 
if (node == NULL) { 
// Индекс не существует 
node = new SparseArray::Node(index, foo, array.cells); 
array.cells = node; 

else 
// 
Индекс уже существует, изменить значение элемента 
node->content 

foo; 
return 
*this; 

ArrayCursor SparseArray::operator[](Index i) 

SparseArray::Node* n = cells; 
while (n != NULL) 
if (n->index = i) 
return 
ArrayCursor(*this, 
n); // 
Существует 
else 


n->next; 
return 
ArrayCursor(*this, 
i); 
// 
Еще не существует 

Ого! Что же происходит в этом хитроумном коде? Все волшебство заключено в двух операторных 
функциях, 
SparseArray::operator[]()
и 
ArrayCursor::operator=()

SparseArray:: 
operator[]()
возвращает 
ArrayCursor
независимо от того, существует индекс или нет (об этом 
ArrayCursor
узнает по тому, какой конструктор был выбран). 
ArrayCursor::operator=(Foo*)
делает одно из двух: если индекс уже существует, элемент изменяется, а если не существует — он 
динамически добавляется в массив. В этом проявляется вся суть курсорности (курсоризма?): 
перегруженный оператор 
=
выполняет присваивание не для самого курсора, а для структуры данных, 
от которой происходит курсор. Теперь присваивание работает независимо от того, существует индекс 
или нет. 
array[Index(17, 29)] = new Foo; 
// Добавляет индекс 
array[Index(17, 29)] = new Foo; 
// Изменяет значение с заданным индексом 
Неплохо для часовой работенки, не правда ли? Наш массив работает совсем как настоящий. Почти. 
Операторы преобразования и оператор -> 
Осталось добавить еще пару штрихов. Во-первых, оператор 
[]
в правой части операции присваивания 
работает уже не так, как было написано, поскольку он возвращает 
ArrayCursor
, а не 
Foo*
или 
Foo*&

Но причин для беспокойства нет, потому что 
Foo*()
в случае необходимости автоматически 
преобразует 
ArrayCursor
к 
Foo*
. Вторая проблема заключается в том, что оператор 
[]
не может 
использоваться слева от оператора 
->
; на помощь приходит 
operator->()




Download 1,95 Mb.

Do'stlaringiz bilan baham:
1   ...   65   66   67   68   69   70   71   72   ...   144




Ma'lumotlar bazasi mualliflik huquqi bilan himoyalangan ©hozir.org 2024
ma'muriyatiga murojaat qiling

kiriting | ro'yxatdan o'tish
    Bosh sahifa
юртда тантана
Боғда битган
Бугун юртда
Эшитганлар жилманглар
Эшитмадим деманглар
битган бодомлар
Yangiariq tumani
qitish marakazi
Raqamli texnologiyalar
ilishida muhokamadan
tasdiqqa tavsiya
tavsiya etilgan
iqtisodiyot kafedrasi
steiermarkischen landesregierung
asarlaringizni yuboring
o'zingizning asarlaringizni
Iltimos faqat
faqat o'zingizning
steierm rkischen
landesregierung fachabteilung
rkischen landesregierung
hamshira loyihasi
loyihasi mavsum
faolyatining oqibatlari
asosiy adabiyotlar
fakulteti ahborot
ahborot havfsizligi
havfsizligi kafedrasi
fanidan bo’yicha
fakulteti iqtisodiyot
boshqaruv fakulteti
chiqarishda boshqaruv
ishlab chiqarishda
iqtisodiyot fakultet
multiservis tarmoqlari
fanidan asosiy
Uzbek fanidan
mavzulari potok
asosidagi multiservis
'aliyyil a'ziym
billahil 'aliyyil
illaa billahil
quvvata illaa
falah' deganida
Kompyuter savodxonligi
bo’yicha mustaqil
'alal falah'
Hayya 'alal
'alas soloh
Hayya 'alas
mavsum boyicha


yuklab olish