Законченный Класс

Программирование без скрытия данных (с применением структур) требует меньшей продуманности, чем программирование со скрытием данных (с использованием классов). Структуру можно определить не слишком задумываясь о том, как ее предполагается использовать. А когда определяется класс, все внимание сосредотачивается на обеспечении нового типа полным множеством операций; это важное смещение акцента. Время, потраченное на разработку нового типа, обычно многократно окупается при разработке и тестировании программы.

Вот пример законченного типа intset, который реализует понятие "множество целых":

class intset { int cursize, maxsize; int *x; public: intset(int m, int n); // самое большее, m int'ов в 1..n ~intset(); int member(int t); // является ли t элементом? void insert(int t); // добавить "t" в множество void iterate(int& i) { i = 0; } int ok(int& i) { return i void error(char* s) { cerr << "set: " << s << "\n"; exit(1); }

Класс intset используется в main(), которая предполагает два целых параметра. Первый параметр задает число случайных чисел, которые нужно сгенерировать. Второй параметр указывает диапазон, в котором должны лежать случайные целые:

main(int argc, char* argv[]) { if (argc!= 3) error("ожидается два параметра"); int count = 0; int m = atoi(argv[1]); // число элементов множества int n = atoi(argv[2]); // в диапазоне 1..n intset s(m,n); while (count maxsize) error("слищком много элементов"); int i = cursize-1; x[i] = t; while (i>0 && x[i-1]>x[i]) { int t = x[i]; // переставить x[i] и [i-1] x[i] = x[i-1]; x[i-1] = t; i--; } }

Для нахождения членов используется просто двоичный поиск:

int intset::member(int t) // двоичный поиск { int l = 0; int u = cursize-1; while (l <= u) { int m = (l+u)/2; if (t < x[m]) u = m-1; else if (t > x[m]) l = m+1; else return 1; // найдено } return 0; // не найдено }

И, наконец, нам нужно обеспечить множество операций, чтобы пользователь мог осуществлять цикл по множеству в некотором порядке, поскольку представление intset от пользователя скрыто. Множество внутренней упорядоченности не имеет, поэтому мы не можем просто дать возможность обращаться к вектору (завтра я, наверное, реализую intset по-другому, в виде связанного списка).

Дается три функции: iterate() для инициализации итерации, ok() для проверки, есть ли следующий элемент, и next() для того, чтобы взять следующий элемент:

class intset { //... void iterate(int& i) { i = 0; } int ok(int& i) { return iiterate(var); while (set->ok(var)) cout << set->next(var) << "\n"; }

Другой способ задать итератор приводится в #6.8.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: