Перегрузка унарных операций

Перегрузим операции “++” и “--”.

Поскольку операция унарная в качестве аргументов передается один параметр:

Tstud& operator ++(Tstud &Stud)

{

++Stud.bal;

return Stud;

}

Tstud& operator --(Tstud &Stud)

{

--Stud.bal;

return Stud;

}

Теперь для переменных (объектов) типа Tstud можно использовать операции инкремент и декремент:

Tstud Student={"Ivanov",3};

++Student;// Student={"Ivanov",4}

--Student--;// Student={"Ivanov",2}

 

Перегрузка унарных операций

Перегрузим операцию “+” для структуры TAB. Поскольку операция бинарная в качестве аргументов передается два параметра:

TAB operator +(const TAB &operand1,const TAB &operand2)

{TAB AB;

AB.A=operand1.A+operand2.A;

AB.B=operand1.B+operand2.B;

return AB;}

Пример использования:

TAB AB1={1.3,2},AB2={2.1,1};

TAB AB3=AB1+AB2; // AB3={3.4,3};

Теперь перегрузим операцию “>” для структуры Tstud. Будем считать, что левый операнд «больше» правого если его поле «bol» больше поля «bol» правого операнда. Результат этой операции должен быть логического типа:

bool operator >(const Tstud &Stud1, const Tstud &Stud2)

{return Stud1.bal>Stud2.bal;}

Пример использования:

Tstud Stud1={"Petrov",3};

Tstud Stud2={"Sidorov",2};

if(Stud1>Stud2)cout<<">"<<endl;

else cout<<"<"<<endl;

Перегрузка следующих операций должна быть осуществлена внутри описания объекта

Перегрузка операции приведения типа

Можно определить функции-операции, которые будут осуществлять преобразование объекта класса к другому типу. Формат:

operator имя_новоготипа ();

Тип возвращаемого значения и параметры указывать не требуется.

Перегрузка операции вызова функции

Формат:

тип operator () (список параметров);

Для примера определим оператор приведения типа int и определим оператор вызова функции, который задает поля структуры:

struct Tstud

{

char FIO[20];

int bal;

operator int() {return (bal); }

void operator()(char* str,int mybal)

{

strcpy(FIO,str);

bal=mybal;

}

};

Пример вызова:

Stud2("Petja",5); // Stud2={"Petja",5}

cout<<(int)Stud2<<endl;// на экран будет выведенно число 5

Потоки и типы, определенные пользователем

Для ввода и вывода в потоках используются перегруженные для всех стандартных типов операции чтения и извлечения << и >>. При этом выбор конкретной операции определяется типом фактических параметров. Для того чтобы вводить и выводить величины типов, определенных пользователем, требуется перегрузить эти операции. Это бинарные операции, левым операндом которых является объект-поток, а правым - объект, который требуется извлечь или поместить в этот поток. Возвращаемое значение должно быть ссылкой на поток, чтобы можно было организовывать цепочки операций, как и в случае стандартных типов.

Формат определения собственной функции вставки:

ostream& operator<<(ostream& имя_потока, Тип объект)

{

Тело функции вставки

return имя_потока;

}

Формат определения собственной функции извлечения:

istream& operator>>(istream& имя_потока, Тип объект)

{

Тело функции вставки

return имя_потока;

}

Определим собственные функции вставки и извлечения для структуры Tstud:

ostream& operator<<(ostream& out,const Tstud &Stud)

{

out<<setw(10)<<setfill('.')<<setiosflags(ios::left)<<Stud.FIO

<<Stud.bal<<endl;

return out;

}

istream& operator>>(istream& in,Tstud &Stud)

{

cout<<"Vvedite FIO\n";

in>>Stud.FIO;

cout<<"Vvedite Bal\n";

in>>Stud.bal;

return in;

}

Пример использования:

Tstud Stud;

cin>>Stud;

cout<<Stud;

В результате будут вызваны функции определенные пользователем.

 

Порядок виконання роботи

 

 

4.4 Контрольні запитання та завдання

 

 

Завдання

Определить основные операции для структуры, перегрузить операции работы с потоками ввода и вывода.

4.6 Варіанти завдань

 

Описания структур взять из лабораторной работы №2

 

Контрольний приклад

 

Определить операции ++, --, >, +, (), приведение к типу int, а также перегрузить операции работы с потоком для структуры студент.

 

#include <iostream>

#include <fstream>

#include <iomanip>

#include <string>

using namespace std;

struct Tstud{

char FIO[20];

int bal;

operator int() const {return (bal); }

void operator()(char* str,int mybal)

{

strcpy(FIO,str);

bal=mybal;

}

 

};

Tstud& operator ++(Tstud &Stud)

{

++Stud.bal;

return Stud;

}

Tstud& operator --(Tstud &Stud)

{

--Stud.bal;

return Stud;

}

Tstud operator +( const Tstud &Stud1, const Tstud &Stud2)

{

Tstud Stud=Stud1;

strcat(Stud.FIO,Stud2.FIO);

Stud.bal+=Stud2.bal;

return Stud;

}

 

bool operator >(const Tstud &Stud1, const Tstud &Stud2)

{

return Stud1.bal>Stud2.bal;

}

ostream& operator<<(ostream& out,Tstud &Stud)

{

out<<setw(20)<<setfill('.')<<setiosflags(ios::left)<<Stud.FIO<<Stud.bal;

return out;

}

istream& operator>>(istream& in,Tstud &Stud)

{

cout<<"Vvedite FIO\n";

in>>Stud.FIO;

cout<<"Vvedite Bal\n";

in>>Stud.bal;

return in;

}

 

int main()

{

Tstud Student1={"Ivanov",3};

Tstud Student2={"Petrov",5};

Tstud Student3;

Student1--;//Student1={"Ivanov",2};

Student2++;//Student2={"Petrov",6};

cout<<Student1<<endl;

cout<<Student2<<endl;

Student3=Student1+Student2;//Student3={"IvanovPetrov",8};

cout<<Student3<<endl;

Student3("Sidorov",5);//Student3={"Sidorov",5};

cout<<Student3<<endl;

if(Student1>Student2)

cout<< Student1.FIO<<" u4itsj lu4she "<<Student2.FIO<<endl;

else cout<< Student2.FIO<<" u4itsj lu4she "<<Student1.FIO<<endl;

const int n=3;

Tstud StudentMas[n];

//организуем ввод и вывод массива структур

for(int i=0;i<n;i++)

cin>>StudentMas[i];

//Вывод на экран

for(int i=0;i<n;i++)

cout<<StudentMas[i]<<endl;

//Вывод в файл

ofstream out("f.txt");

for(int i=0;i<n;i++)

out<<StudentMas[i]<<endl;

cin.get();

return 0;

}

 

Результаты работы программы:

Ivanov……….2

Petrov………..6

Ivanov Petrov..8

Sidorov………5

Petrov u4itsj lu4she Ivanov

Vvedite FIO

Петров

Vvedite Bal

Vvedite FIO

Сидоров

Vvedite Bal

Vvedite FIO

Максименко

Vvedite Bal

 


5 Основи розробки класів у мові С++

 

Мета роботи

 

5.2 Вказівки щодо організації самостійної роботи студентів

 

Классы и объекты

Классэто такой программный тип, который определяет не только данные, но и функции, применимые к этим данным. Говорят, что данные задают состояние объекта, а функции – его поведение.

В С++ объявление класса похоже на структуру в языке С, но, помимо компонентов-данных, включает компоненты-функции, которые также называют методами.

 

Пример. Объявление класса “дата”. Хранит день, месяц, год. Способен установить дату, сообщить ее, и изменить на следующую.

ß

class date

{

public:

int day, month, year;

void set (int, int, int);

void get (int&, int&, int&);

void next ();

};

 

Определение функций-компонент можно расположить внутри или за пределами объявления класса. В первом случае транслятор попытается создать функции inline. Во втором — имени определяемой функции должно предшествовать имя класса вместе с операцией разрешения видимости.

Все данные класса доступны из методов того же класса.

 

Пример. Определение функции-члена date::set, расположенное за пределами объявления класса.

 

void date::set (int d, int m, int y) {

day = d;

month = m;

year = y;

}

 

Класс представляет собой тип данных. Сами же данные такого типа называют экземплярами класса или объектами. Каждый объект имеет собственную копию всех данных класса. Чтобы создать объект в памяти, его надо определить, например,

date d;

 

После создания объекта получить доступ к его данным и методам можно при помощи операции прямого выбора, обозначаемой точкой.

ß

cout << d.day;

d.set(19,10,2001);

Инкапсуляция

Инкапсуляция в объектно-ориентированном программировании — это сокрытие деталей реализации класса. Класс вводит еще одну область видимости (другие области это файл, функция, блок, прототип функции, пространство имен). В пределах класса видимы все его компоненты, за пределами — только некоторые.

Спецификации доступа public и private регулируют видимость компонент извне.

 

Пример. Данные класса date скрыты от пользователя, а методы открыты.

ß

class date

{

private:

int day, month, year;

public:

void set (int,int,int);

...

};

 

Члены класса всегда можно именовать, применяя операцию разрешения области видимости, например, вместо

 

int day, month, year;

 

в объявлении класса можно написать

 

int date::day, date::month, date::year;

 

но обычно операция разрешения видимости применяется за пределами объявления класса.

Конструктор

После создания объекта в памяти все его данные должны получить значения. Конструктор — это функция, специально предназначенная для инициализации объекта. Конструктор носит то же имя, что и класс и не возвращает значения. Класс может иметь несколько конструкторов.

Пример. Класс с тремя конструкторами.

ß

class date {

int day, month, year;

public:

date(int,int,int);

date(char*);

date();

};

 

Конструктор вызывается тогда, когда создается объект. Благодаря конструкторам, оператор объявления в С++ вызывает выполнение действий.

 

Примеры инициализации объектов:

 

int main(int argc, char* argv[])

{

date d1 = date(19, 10, 2001);

date d2(19, 10, 2001); // то же, но сокращенно

date d3 = date("19-Oct-2001");

date d4 = "19-Oct-2001"; // когда в конструкторе ровно 1 параметр

date d5; // работает конструктор без параметров

return 0;

}

 

Если программист не определил конструктор, транслятор сам строит конструктор по умолчанию, который не имеет параметров и ничего не делает. При наличии в классе других конструкторов конструктор без параметров требует от программиста явного определения.

Деструктор

Деструктор решает задачу, обратную задаче конструктора. Он вызывается всякий раз, когда объект уничтожается. Имя деструктора состоит из знака тильды “~” и имени класса. Например,

~date() .

 

Деструктор не имеет аргументов и не возвращает значения. Компилятор сам генерирует деструктор, если программист его не определил. Когда объект выходит из области видимости, деструктор вызывается автоматически.

Указатели на объекты

Объявление date* p создает указатель на объект класса date. Если p указывает на объект, обратиться к его членам можно при помощи операций (*p).set(), но для этого существует специальная операция косвенного выбора

p->set()

 

Указателю можно присвоить адрес уже существующего объекта.

ß

date d1;

date* p = &d1;

 

Каждый объект имеет указатель на себя, который обозначается идентификатором this. Он является скрытым параметром каждой функции-члена. Для класса X указатель this имеет тип:

 

X* const this;

 

Функцию-член можно объявить так, чтобы поля объекта были доступны ей только для чтения

 

int readme() const {/*тело функции*/};

 

Указатель this, передаваемый такой функции, будет иметь тип:

 

const X *const this.

Операции new и delete

Объект размещается в динамической памяти при помощи операции new.

ß

date* p = new date(19, 10, 2001);

 

Если выделить память не удалось, то по новому стандарту возбуждается исключение, по старому – возвращается 0.

Замечание. Программист может перегрузить операцию new для своего объекта и, тем самым, изменить ее поведение.

 

Удаляется объект из динамической памяти операцией delete.

ß

delete p;

Дважды удалять из динамической памяти один и тот же объект нельзя!