Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь FAQ Написать работу КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Перегрузка оператора ввода из потокаСодержание книги
Поиск на нашем сайте
Также возможна и перегрузка оператора ввода из потока», с ее помощью можно научить C++ читать из потока объекты класса. В листинге 15.9 к возможностям программы-примера POINTOUT.CPP из предыдущего раздела добавляются возможности чтения из потока. Листинг 15.9. POINTIN.CPP (классы и потоки ввода) «include <iostream.h> class TPoint { private: int x, y; public: TPoint() { x = у = 0; } TPoint(int xx, int yy) { x = xx; у = yy; } void PutX(int xx) { x = xx; } void PutY(int yy) { у = yy; } int GetX(void) { return x; } int GetY(void) { return y; } friend ostream& operator<<(ostream& os, TPoint &p); // дружественная функция-член ввода из потока operator»() friend istream& operator>>(istream& is, TPoint &p); }; TPoint p; cout «p «'\n'; p.PutX(100); p.PutY(200); cout «p «'\n'; cout << "\nEnter x and у values: "; cin» p; cout << "\nYou entered: "«p; return 0; } ostream& operator«(ostream& os, TPoint &p) { os «"x == " «p.x «", у == " «p.у; return os;} // читаются значения для х и у с помощью // ссылки is на istream. // Функция возвращает ссылку is, т.о. // можно вводить несколько значений // в одном операторе ввода. istream& operator>>(istream& is, TPoint &p){ is» p.x» p.y; return is;} В строке 14 для класса TPoint объявляется дружественная функция-член ввода из потока operator»(), аналогичная функции перегрузки оператора вывода в поток, приведенной в предыдущем разделе, только вместо ostream используется istream. В реализации функции (строки 37-41) читаются значения для х и у с помощью ссылки is на istream. Функция возвращает ссылку is, таким образом можно вводить несколько значений в одном операторе ввода. При запуске программы на выполнение запрашиваются два значения для х и у. Введите два целочисленных значения, разделенных пробелом. Оператор ввода из потока в строке 26 сохранит оба введенных вами значения в объекте класса, которые затем отобразятся в строке 27. Шаблоны Подобно тому как класс представляет собой схематическое описание построения объекта, так и шаблон представляет собой схематическое описание построения функций и классов. Шаблоны особенно полезны в библиотеках классов, которыми пользуются многие программисты. Шаблоны, иногда также называемые параметризованными типами, указывают лишь спецификации для функций и классов, но не детали настоящей реализации. Шаблонные функции Шаблоны функций описывают общие свойства функций, подобно рецепту приготовления пирожного. Шаблоны функций, обычно объявляемые в заголовочном файле, имеют следующий общий вид:
template<class T> void f(T param){ // Тело функции} //Т — определяемое пользователем //имя функции
Шаблонная функция начинается строкой template<class Т>, указывающей компилятору, что Т — определяемое пользователем имя функции. (Вы можете заменить Т на любое другое имя, если захотите.) Необходим, по крайней мере, один параметр Т для передачи функции данных для обработки. Можно также задать указатель (Т* param) или ссылку (Т& param).
Функция может объявлять несколько параметров и возвращать значение типа Т: template<class T> T f(int а, Т b) { // Тело функции} //ф-ция f() возвращает значения типа //Т и имеет два параметра — целое с //именем а и неопределенный объект //Т с именем b.
В этой версии шаблонная функция f() возвращает значения типа Т и имеет два параметра — целое с именем а и неопределенный объект Т с именем Ь.
Пользователи шаблона укажут действительный тип данных для Т.
Например, в программе можно задать следующий прототип: double f(int a, double b); //Если это обычная функция, мы //должны обеспечить ее реализацию, //т.к. f() — шаблонная функция, //компилятор реализует код функции, //заменив Т в данном случае на // double. ПРИМЕР 4.10: … как с помощью шаблонов можно уменьшить размер и сложность программ, предоставив компилятору реализацию обобщенных функций. Листинг 4.10. MINMAX.H (шаблоны функций min и max) // minmax.h -- Шаблоны функций min и max #ifndef MINMAX_H #define MINMAX_H 1 // Предотвращение повторных include //Т заявлен неопределенным типом, // объект которого возвращает //шаблонная функция mах() template<class T> T max(T a, T b) { //схема для реальных операторов, которые //будут сгенерированы позже if (a > b) return a; Else return b;} template<class T> T min(T a, T b) { if (a < b) return a; Else return b;} #endif // _MINMAX_H Рассмотрим подробнее строку 6. В ней Т заявлен неопределенным типом, объект которого возвращает шаблонная функция mахО. Кроме того, функции mах() необходимы два аргумента типа Т. Операторы в функции, приведенные в строках 8-11 — схема для реальных операторов, которые будут сгенерированы позже, когда будет задан действительный тип Т. Шаблон функции min() объявляется аналогичным образом. В программе, использующей шаблонные функции, необходимо лишь указать их прототипы, которые компилятор использует для создания действительных тел функции. В листинге 4.11 приводится пример такой программы. Листинг 4.11. FTEMPLAT.CPP (использование шаблонов функций) //4_11.cpp //использование шаблонов функций) #include <iostream.h> #include <conio.h> #include "minmax.h" int max(int a, int b); // три прототипа шаблонной //перегруженной ф-ции mах() double max(double a, double b); char max(char a, char b); Main() {int i1 = 100, i2 = 200; double d1 = 3.14159, d2 = 9.87654; char c1 = 'A', c2 = 'z'; cout << "max(i1,i2) =="<< max(i1, i2) << '\n'; cout << "max(d1,d2) =="<< max(d1, d2)<<'\n'; cout << "max(c1,c2) =="<< max(c1,c2) << '\n'; //Все функции mах() возвращают //объекты различных типов данных и //требуют два аргумента этих же //типов. getch(); return 0; } В строках 4-6 объявляются три прототипа шаблонной функции mах(). Эти строки дают компилятору необходимую информацию для реализации трех перегруженных функций mахО. Все функции mахО возвращают объекты различных типов данных и требуют два аргумента этих же типов. В основной программе функции mахО вызываются в строках 14-16. Вы можете пользоваться шаблонными функциями точно так же, как и обычными.
Можно использовать более одного неопределенного типа. Для объявления mах() с двумя различными неопределенными типами можно написать: template<class T1, class T2> T1 max(T1 a, T2 b) //функция mах() будет возвращать \\значение типа Т1, и ей необходимы \\два аргумента: один -1 типа Т1, \\другой — типа Т2.
Шаблонные классы Шаблонные классы предоставляют еще большие возможности, чем шаблонные функции. Шаблон класса обеспечивает скелет обобщенного класса для его последующей реализации. Как и шаблоны функций, шаблоны классов чаще всего объявляются в заголовочных файлах.
Объявление шаблона класса имеет следующий общий вид: template<class T> class TDatabase { // Закрытые, защищенные и //открытые члены класса } где T - неопределенный тип, задаваемый пользователем шаблона. (Можно заменить Т на любой другой идентификатор, если захотите.) Т можно впоследствии заменить любым встроенным типом, другим классом, указателем и т.д. TDatabase — имя шаблонного класса. Для ясности заголовок шаблона лучше объявлять в отдельных строках: template<class T> class TAClass { . } Можно также указать несколько неопределенных типов: template<class T1, class T2, class T3> class TAnotherClass { }
ПРИМЕР:4.12: демонстрация объявления шаблона класса, реализующего базу данных с небольшим числом записей.
Листинг 4.12. DB.H (шаблон класса TDatabase) В шаблоне класса класс Т можно использовать для объявления данных-членов, типов возвращаемых функциями-членами значений, параметров и прочих элементов неопределенных типов.
// db.h -- Объявление шаблонного класса TDatabase #ifndef __DB_H #define __DB_H 1 // Предотвращение нескольких template <class T> class TDatabase { private: T *rp; //указ-тель на записи Int num; //число записей public: TDatabase(int n) //\\выделяет память для массива //объектов Т { rp = new T[num = n]; } ~TDatabase() { delete[] rp; } void DoNot(void); T &GetRecord(int recnum); }; template<class T> void TDatabase<T>::DoNot(void) {} template<class T> // возвращает ссылку на объект типа //Т, идентифицируемый номером //записи recnum. T TDatabase<T>::GetRecord(int recnum) { T *crp = rp; // Указатель на текущую запись = указатель на записи if (0 <= recnum && recnum < num) while (recnum-- > 0) crp++; return *crp; } //#endif //__DB_H
Например, в объявлении класса TDatabase в строке 9 объявляется указатель на Т с именем гр: T *rp; На этой стадии настоящая природа Т еще не известна, поэтому в программе его можно использовать только в самых общих случаях. конструктор TDatabase в строках 12-13 выделяет память для массива объектов Т, присваивая адрес массива указателю гр и заодно устанавливая член num равным требуемому числу записей. (Для простоты в классе игнорируются все связанные с выделением памяти ошибки, которые могут возникнуть.) В строке 15 этот массив удаляется с помощью оператора специального вида delete[] с целью обеспечения вызова деструктора для массива, содержащего объекты класса. В строке 17 объявляется функция-член GetRecordO, возвращающая ссылку на объект типа Т, идентифицируемый номером записи recnum. Это еще один вид обобщенной операции, не требующей знания определенного типа Т. Функции-члены шаблонного класса могут реализоваться встраиваемыми, как это показано на примере конструктора и деструктора класса TDatabase. Или же они могут реализоваться отдельно. Конечно, поскольку эти функции-члены шаблонного класса пока остаются только объявлениями, их вполне можно поместить в заголовочный файл, а не в отдельный модуль. Функция DoNotO, которая, как подсказывает ее имя, не выполняет никаких действий, демонстрирует общий вид реализации функций-членов шаблонного класса: template<class T> void TDatabase<T>::DoNot(void) { Заголовок функции-члена предварен фразой template<class T>. Затем следует тип возвращаемого функци-1 ей значения (void), имя класса (TDatabase<T>) и оператор разрешения области видимости (::). Последним! идет объявление самой функции (DoNothing(void)) и тело (пустое, в данном случае). Используйте этот пример как образец для написания ваших собственных функций-членов шаблонных классов. В строках 25-33 демонстрируется более сложный пример функции-члена шаблонного класса вместе с опера-1 торами, реализующими действия функции. Функция GetRecordO возвращает ссылку на объект типа Т. Внутри функции указатель сгр типа Т присваивается указателю того же типа с именем гр. Иными словами, указатель сгр ссылаетсяна первую запись, сохраненную в объекте класса TDatabase. В строке 29 проверяется, соответствует ли параметр recnum допустимому диапазону значений. Если да, цикл while в строках 30-31 декрементирует параметр recnum до нуля и одновременно передвигает указатель сгр на одну запись в базе данных. Обратите внимание на строку 31. Инкрементирование указателя р с помощью выражения р++ сдвигает I указатель на число байтов объекта, на который ссылается р. В классе Database даже несмотря на то, что тип объекта, на который ссылается сгр, не известен, вполне приемлемо выражение сгр++. Позже, когда будет задан действительный тип для шаблона класса, компилятор сможет сгенерировать соответствующие инструкции для увеличения указателя сгр на величину sizeof(T). Без шаблонных классов подобные обобщенные операторы было бы не так-то легко написать. В строке 32 возвращается разыменованное значение указателя сгр — другими словами, ссылка на любой] объект, адресуемый сгр. Это завершает объявление шаблона класса, в котором не делается никаких предположений о том, какого типа данные в нем запоминаются. Следующий шаг — использование шаблона для создания объекта класса базы данных, способного запомнить некоторое число записей. В листинге 4.13 демонстрируется работа шаблона класса TDatabase.
Листинг 4.13. CTEMPLAT.CPP (использование шаблонов класса) //4_13.cpp #include <conio.h> #include <iostream.h> #include <string.h> #include "db.h" class TRecord { private: char name[41]; public: TRecord () { name[0] = 0; } TRecord(const char *s) { Assign(s); } void Assign(const char *s) { strncpy(name, s, 40); } char *GetName(void) { return name; } };//class int main() {
|
||||
Последнее изменение этой страницы: 2016-08-01; просмотров: 282; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.15.26.184 (0.007 с.) |