lk_oop-c_4-11.ppt
- Количество слайдов: 22
Лекция № 4 по дисциплине «Объектно-ориентированное программирование» на тему: Статические объекты и функции. Перегрузка операций
Копирующий конструктор Когда один объект присваивается другому, выполняется почленное копирование всех его членов-данных. Присвоить объекту А объект В можно, если их тип совпадает Time t 1(1, 3, 2011); //конструктор инициализации Time t 2=t 1; // конструктор копирования Компилятор автоматически создает копирующий конструктор, если он не определен программистом явно Пример явного определения копирующего конструктора. Time(const Time &t) { day=t. day; month=t. month; year=t. year; }
Вызов копирующего конструктора происходит в следующих случаях: в операторе объявления Time t 2=t 1; когда объект передается функции как параметр; когда объект возвращается в качестве значения функции Пример 1. Time t 1(1, 3, 2011); f(t 1); Пример 2. f(Time(1, 3, 2011));
Массивы объектов Объекты можно объединять в массивы: Time t 1[5]; Массивы можно инициализировать с помощью списков инициализации. Time t 1[2]={Time(1, 1, 2011), Time(1, 3, 2011)}; Time t 2[2]={Time(“ 01 -Jan-2011”), Time(“ 01 -Mar-2011”)}; Time t 3[2]={“ 01 -Jan-2011”, “ 01 -Mar-2011”}; В динамической памяти массивы объектов размещаются при помощи операции new: Time *t= new Time[5]; При размещении в динамической памяти элементы массива объектов инициализируются только конструктором без параметров, поэтому он обязательно должен существовать
Статические переменные и функции Статическая переменная является общей для всех объектов данного класса Объявление статического элемента начинается с ключевого слова static Статические элементы должны быть инициализированы только один раз Статическая переменная может быть объявлена, но не может быть определена в объявлении класса
class A { public: static int S; }; int A: : S=0; Пример объявления статической переменной Обращение к открытой статической переменной: объект_класса. имя_переменной указатель_на_объект-> имя_переменной имя_класса : : имя_переменной К закрытым статическим переменным обращение должно происходить при помощи открытых членов-функций класса. t. Ptr->get. Count() Time: : get. Count()
Указатель на себя Каждый объект имеет указатель на себя, который обозначается идентификатором this. Он является скрытым параметром каждой член-функции Тип указателя this зависит от типа объекта. В не-константной член-функции класса Time указатель this имеет тип Time *const Примеры: this->day (*this). day
Перегрузка операций Чтобы разрешить операциям С++ работать с объектами класса, их необходимо перегрузить Операции перегружаются при помощи написания обычного определения функции, но именем функции должно быть ключевое слово operator и символ перегружаемой операции. Например, operator+ перегружает операцию сложения.
Перегрузка операций Операция присваивания может использоваться с любым классом без перегрузки Операция адреса & также может использоваться с объектами любого класса без перегрузки Часто перегрузить требуется не одну операцию, а целый перечень, например, +, -, /, *. Чаще всего перегружающей функцией делают членфункцию класса, или дружественную функцию.
Перегрузка операций Большая часть операций С++ может быть перегружена: + - * / % & ! < > = += - = *= /= << >> && ++ -- new delete Не могут быть перегружены: . : : ? : sizeof Перегружать оператор-функцию можно многократно Приоритет операций не может быть изменен посредством перегрузки
Пример перегрузки сложения для класса комплексных чисел class Complex{ private: float re, im; public: Complex (float r, float i){ re=r; im=i; } Complex operator+(Complex); };
Продолжение примера Complex: : operator+(Complex c){ // перегружаем //сложение Complex rez; rez. re=re+c. re; rez. im=im+c. im; return rez; } int main() { // тестирующая функция Complex c 1= Complex (2, 5); Complex c 2= Complex (5, 10); Complex d; d=c 1+c 2; // благодаря перегрузке такая операция //возможна }
Пример перегрузки обычной функцией с двумя аргументами Complex operator+ (Complex &first, Complex &second) { Complex rez; rez. re=first. re+second. re; rez. im= first. im+second. im; return rez; } Нельзя изменить число операндов, которое подразумевает операция Нельзя создавать новые операции. Допускается перегрузка только существующих операций
Пример перегрузки операций передачи в поток и извлечения из потока #include <iostream. h> #include <iomanip> using std: : setw; class Phone { //опишем класс телеф. номеров friend ostream & operator<< (ostream&, const Phone&); friend istream & operator>> (istream&, Phone&); private: char area. Code[4]; // 3 цифры кода области и null char exchange[4]; // 3 цифры кода АТС и null char line[5]; // 4 цифры линии и null
Продолжение примера ostream & operator<< (ostream& output, const Phone &num) { output<<”(”<<num. area. Code<<”)” <<num. exchange <<””<<num. line; return output; } istream &operator>> (istream &input, Phone &num) { input. ignore(); // пропустить ( input>> setw(4) >> num. area. Code; // ввести код //области input. ignore(); // пропустить ( и пробел input>> setw(4) >> num. exchange; // ввести код ATC
Окончание примера input. ignore(); input>> setw(5) >> num. line; return input; } int main() { Phone ph; cout<< “Введите телефонный номер”; cin>>ph; cout<< “The phone number is” << ph<< endl; return 0; }
Каскадирование операций >> и << Выражение cin>>ph преобразуется компилятором в вызов функции operator>>(cin, ph); Функция operator>> возвращает input как ссылку на istream. Это разрешает каскадирование операций ввода объектов Phone. Например: cin>>ph 1 >> ph 2; Сначала будет выполнено cin>>ph 1 посредством вызова функции operator>>(cin, ph 1); Этот вызов вернет cin как значение выражения cin>>ph 1, оставшаяся часть выражения будет проинтерпретирована как cin>>ph 2.
Перегрузка унарных операций Унарная операция может быть перегружена: как не-статическая член-функция без аргументов как обычная функция с одним аргументом Пример. Перегрузка унарного минуса. Complex: : operator-() { return Complex (-re, -im); } Другой вариант этой же операции: Complex& Complex: : operator-() { re=-re; im=-im; return *this; }
Перегрузка инкремента Пример. Перегрузка префиксного инкремента. Complex& Complex: : operator++() { ++re; ++im; return *this; } Если компилятор встречает постинкремент с1++, он генерирует вызов функции с1. operator++(0); Прототип объявляется как Complex operator++(int); Пример. Перегрузка постфиксного инкремента. Complex: : operator++(int) { return Complex(++re, ++im); }
Перегрузка оператора присваивания Операция присваивания по умолчанию определена для любого класса и состоит в почленном копировании нестатических элементов класса. Пример. Complex& Complex: : operator=(Complex &c) { re=c. re; im=c. im; return *this; }
Перегрузка оператора индекса массива Пример. class Day { public: char* operator[] (int n) { switch(n) { case 1: return “Понедельник”; case 2: return “Вторник”; case 7: return “Воскресенье”; default: return “”; } } }; Day d; cout << d[2]; // выводит «Вторник»
Перегрузка преобразования типов Операция преобразования применяется к объекту класса, преобразуя его в объект другого класса или в объект встроенного типа. Прототип функции А: : operator char*(); объявляет перегруженную член-функцию приведения для создания объекта char* из объекта типа А. Если а – объект класса А, то, когда компилятор встречает выражение (char*)а, он генерирует вызов а. operator char*(); Пример. А: : operator int(); объявляет перегруженную член-функцию для преобразования объекта типа А в целый тип.
lk_oop-c_4-11.ppt