![]() Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь 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; просмотров: 297; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.140.247.58 (0.011 с.) |