|
Программирование >> Унарные и бинарные операторы
Шаблоны классов 207 вает зпачеьпш NULL - так в С++ принято обозначать заведомо песуществуюншй адрес. Сначала число .элементов массива len равно нулю, а новые элементы, как и в контейнерных классах, таких как vector, добавляются функцией pushbackO. Кроме того, интерфейс класса содержит enie функцию lengthO, нозвшяющую получить гекущи!! размер массива, а также оператор доступа к произвольному элементу []. Обратите внимание, оператор [] возвращает ссьику па элемент массива, чтобы можно было присвоить ему повое значение, то есть поставить оператор [] слева от знака равенства ([]=). Кроме интерфейсных, в области private объявлены две служебные функции check() и expand(), помогающие управлять классом. Пс1)в;1я провс11яст, укладывается ли индекс в границы массива, вторая добавляет к нему новый элемент. Эти функции ие видны пользователям класса, поэтому их можно как уго/цго менять без yniep-ба для пгггерфейса R листинге 11.2 эти функции только объявлены, их вда.чожная реализация показана в листинге 11.3. Листинг 11.3 tempiate<typename Т> void array<T> :: checkCint n){ if((n < 0) II (n >= 1en)){ cout Неверный индекс endl: exit(l): template <typename T> void array<T> :: expand(){ T* temp = new T[++1en]: прололжение Значение NULL па самом деле равно пулю, и вместо a(NULL) в коне грукгоре можно писать а(0), по NULL паглядпей - cpa:iy нндпо, что перед на.ми указатель. ваний можно продолжить, создав идею идеи , то есть шаблон класса. Попробуем приоткр1>1ть завесу над контейнерными типами, которыми много раз уже пользовались, и создадим пример усовершенствованного .массива, в котором можно хранить разные объекты. Предусмотрим, кроме того, возможность менять его раз.меры, а также проверять верность индекса в операторе []. Пример класса array показан в листинге 11.2. Листинг 11.2 template <typename Т> class array { public: arrayO : len(O). a(NULL){} -arrayO {delete [] a:} void push back(T e){ expand(): a[1en-l] = e: T & operator[](int n){ check(n): return a[n]: } int lengthO {return(len):} private: T* a: указатель на нулевой объект int len; число элементов void checkCinf n): void expand0: } Шаблон класса, судя по этому листингу, создастся так же, как и для функции: перед определением класса ставится признак пшблопа tempi ate <typename Т>, где Т обозначает некий тип объекта. Основой будун1сго массива служит указатель Т *а, которому при создагп1и объекта конструктор присвап- 208 Глава 11. Шаблоны Листинг 11.3 (продолжение) ifClen * 1){ fordnt 1 = 0; i < len: tempCi] = a[i]: delete [] a; a - temp; } Her ничего удивительного, что в шаблоне класса задаются шаблоны функций. Каждая функция начинается словами tenplate <typenarne Т>, далее оператор :: показывает, что функция принадлежит шаблону класса array: void array<T> :: expandO Обратите внимание, что шаблон класса обозначается его именем и стоящим далее в треугольных скобках параметром: аггау<Т> Нам осталось понять устройство собственных функций. В функции checkC), предназначенной для прерывания работы программы, когда индекс массива выходит за допустимые пределы, используется функция exi t (1), возвращающая операционной системе код ошибки 1. Функция expandC) выделяет область памяти, куда помещается на один элемент больше, затем переписывает туда все элементы массива, далее освобождает занимаемую им память и, наконец, засылает адрес нового массива в указатель а. После создания шаблона можно попробовать его в деле с объектами разной природы. Программа, показанная в листинге 11.4, использует шаблон класса array, помещенный в файл array.h (в него вошли листинги 11.2 и 11.3). Листинг 11.4 #i ncl ude <iostreani> using namespace std: Шаблоны классов 209 include array.h листинги 11.2. 11.3 int main(){ array<int> ia: array<char*> sa: ia.push back(10); ia.push back(20): forCint i = 0: i < ia.lengthO: i++){ cout ia[i] endl: } ia[0]=5: cout ia[0] endl: 5 sa.push back( Maria! ): sa.push back( fl боюсь! ): forCint i = 0: i < sa.lengthC): i++){ cout sa[i] endl: returnCO); } Шаблон используется в программе для создания массива целочисленных переменных (array<int> ia:) и массива указателей на char (array<char*> sa:). Далее в оба массива функция pushbackC) запихивает по два значения, и если добавление целочисленных элементов пояснений не требует, то о массиве указателей стоит сказать несколько слов. Инструкция sa. pushback С Мама! ) может показаться непонятной и опасной, потому что не видно, когда для строки Мама! вьщеляется память. Но дело в том, что компилятор С++, встретив инструкцию Char *а= Мама! , автоматически выделяет память для пяти символов Мама! и завершающего шестого символа (\0), а затем также автоматически засылает в переменную а адрес буквы М . Так что в массиве sa окажутся нужные указатели, и на экран будут выведены ожидаемые строки Мама! и Я боюсь! . Задача 11.1. Напишите конструктор копии для класса array. 210 Глава 11. Шаблоны Задача11.2. Функция expandO класса array увеличивает размер массива на едиьи1цу. Между тем частые вызовы функции pushbackO занимают много времени, ведь каждый раз нужно перемещать массив на новое место. Чтобы программа работала быстрее, создайте 1наблон класса array, где функция expand() удлиняет массив сразу на несколько элементов. ГЛАВА 12 Ввод-вывод
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |