27
Модуль 3 : Основные понятия объектно-ориентированного программирования. Темы лекции : Продолжение введения в ООП.Перегрузка операций. Практическое задание : Перегрузка операций. Тренер: Игорь Шкулипа, к.т.н. C ++ Базовый. Занятие 9

C++ Базовый. Занятие 09

Embed Size (px)

Citation preview

Модуль 3: Основные понятия объектно-ориентированного программирования.

Темы лекции: Продолжение введения в ООП.Перегрузка операций.

Практическое задание: Перегрузка операций.

Тренер: Игорь Шкулипа, к.т.н.

C++ Базовый. Занятие 9

http://www.slideshare.net/IgorShkulipa 2

Продолжение введения в ООП

http://www.slideshare.net/IgorShkulipa 3

Дружественные функции

Дружественные функции – это функции, объявленные вне класса,но имеющие доступ к закрытым и защищенным полям данного класса

Дружественная функция объявляется внутри класса с модификаторомfriend

Дружественные функции не являются членами класса, поэтому им непередается указатель this

Дружественные операции, как и дружественные функции, могутиметь доступ к приватным и защищенным методам класса

class Class1

{

friend void FriendMethod();

};

http://www.slideshare.net/IgorShkulipa 4

Дружественные классы

Некоторым классам может понадобиться доступ к закрытым данным другдруга.

В этом случае необходимо объявить дружественный класс внутриопределения класса

class Class1;

class Class2

{

friend class Class1;

private:

int data;

};

Дружественная связь между классами является самой сильной.

Реализации классов оказываются связанными, что противоречитпринципу инкапсуляции.

(!) Не используйте дружественные классы до тех пор, пока ихиспользование не окажется единственным способом решения задачи

http://www.slideshare.net/IgorShkulipa 5

Статические данные и методы

Для каждого объекта создается своя собственная копия членов данных.

Для некоторых классов было бы удобно использовать данные, общиедля всех экземпляров данного класса (например, строковоепредставление имени класса или константы, общие для всехэкземпляров класса, область видимости которых должна бытьограничена методами класса)

Такие поля и методы называют статическими и объявляют при помощиключевого слова static

class Class1

{

static void StaticMethod();

};

http://www.slideshare.net/IgorShkulipa 6

Особенности статических методов

◦ Статические методы не получают указатель this.

◦ Статические методы могут обращаться только к статическим даннымкласса.

◦ Статические методы могут вызывать только статические методы(либо нестатические, если им передается указатель или ссылка наобъект класса).

◦ Статические методы имеют доступ к закрытым и защищенным полями методам класса, через экземпляры классов.

◦ Доступ к статическим методам и данным класса осуществляется поимени класса (создавать экземпляр не требуется).

http://www.slideshare.net/IgorShkulipa 7

Применение статических методов

◦ Паттерн «одиночка» (singleton).

◦ Объект с глобальным доступом, существующий в программе вединственном экземпляре.

◦ Методы и данные, характерные для класса в целом, а не дляотдельных его экземпляров.

◦ Создание классов-утилит

http://www.slideshare.net/IgorShkulipa 8

Вложенное объявление классов

Язык C++ позволяет разместить объявление одного класса (или другоготипа данных) внутри объявления другого.

Это полезно, когда вложенный тип данных используется только внешнимклассом, или совместно с ним.

Использование вложенного класса может происходить двумя способами:

⚫ Из методов внешнего класса – по имени вложенного класса

⚫ Снаружи – при помощи указания имени внешнего класса:ExternalClass::InternalClass

http://www.slideshare.net/IgorShkulipa 9

Пример вложенного объявления классов

class ExternalClass

{

public:

class InternalClass

{

public: void InternalMethod();

};

private:

void ExternalMethod()

{

InternalClass inClass;

inClass.InternalMethod();

}

};

void main()

{

ExternalClass::InternalClass inClass;

inClass.InternalMethod();

}

http://www.slideshare.net/IgorShkulipa 10

Шаблоны проектирования (паттерны)

Шаблон проектирования – это архитектурная конструкция,представляющая собой решение проблемы проектирования врамках некоторого часто возникающего контекста.

http://www.slideshare.net/IgorShkulipa 11

Шаблон «Одиночка» (Singleton)

#include <iostream>

using namespace std;

class Singleton

{

public:

static Singleton* GetInstance()

{

if (_instance==NULL) _instance= new Singleton();

return _instance;

}

void Method1(){cout<<"Method1\n";}

void Method2(){cout<<"Method2\n";}

private:

Singleton(){}

static Singleton* _instance;

};

Singleton::_instance=NULL;

int main()

{

Singleton* singleton = Singleton::GetInstance();

singleton->Method1();

singleton->Method2();

}

http://www.slideshare.net/IgorShkulipa 12

Применение Singleton

Применяется, когда нужен только один экземпляр класса.Например для хранения глобальной конфигурации системы,для ведения логов, связи с базой данных и т.д.

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

http://www.slideshare.net/IgorShkulipa 13

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

http://www.slideshare.net/IgorShkulipa 14

Для чего нужна перегрузка операций

Для некоторых типов данных естественными может оказатьсяиспользование операций над базовыми типами:

⚫+= и + для конкатенации строк

⚫ -- и ++ для итераторов

⚫ арифметические операции для векторов и комплексныхчисел

⚫ [] для векторов и матриц

⚫= для классов с собственным конструктором копирования

⚫ операции сравнения для строк и других типов

http://www.slideshare.net/IgorShkulipa 15

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

Для пользовательских типов данных C++ позволяет задатьсобственные операции

⚫Некоторые из них всегда определяются внутри класса

⚫=, +=, -=, *= и т.д.

⚫Некоторые – снаружи (операции, в которых применяютсябазовые типы).

⚫Некоторые – где угодно.

Синтаксис:

<тип> operator <О>(параметры)

http://www.slideshare.net/IgorShkulipa 16

Ограничения

◦ Приоритет операций над пользовательскими типами тот же,что и для базовых типов

◦ Нельзя переопределить операции точка (.) и sizeof

◦ Бинарные операции остаются бинарными, унарные -унарными

http://www.slideshare.net/IgorShkulipa 17

Пример

class Complex

{

private:

double _im;

double _re;

public:

Complex();

Complex(double );

Complex(double, double);

~Complex();

}

Задача: выполнить перегрузку операций для нового типаданных.

http://www.slideshare.net/IgorShkulipa 18

Класс «Комплексное число»class Complex

{

private:

double _im;

double _re;

public:

Complex();

Complex(double );

Complex(double, double);

Complex (Complex &c);

~Complex();

Complex operator = (Complex &c)

{ this->SetIm(c.GetIm()); this->SetRe(c.GetRe()); return (*this); }

friend bool operator ==(const Complex& left, const Complex& right);

friend Complex operator +(const Complex& left, const Complex& right);

friend Complex operator -(const Complex& left, const Complex& right);

friend Complex operator *(const Complex& left, const Complex& right);

double GetRe(){return _re;}

double GetIm(){return _im;}

void SetRe(double re){_re=re;}

void SetIm(double im){_im=im;}

}

http://www.slideshare.net/IgorShkulipa 19

Конструкторы и деструктор

Complex::Complex()

:_re(0), _im(0)

{

}

Complex::Complex(double re)

:_re(re), _im(0)

{

}

Complex::Complex(double re, double im)

{

_re=re; _im=im;

}

Complex::Complex (Complex &c)

{

_re=c.GetRe(); _im=c.GetIm();

}

Complex::~Complex()

{

}

http://www.slideshare.net/IgorShkulipa 20

Операция сравнения

bool operator ==(const Complex& left, const Complex& right)

{

if ((left.GetRe()==right.GetRe()) &&

(left.GetIm()==right.GetIm()))

{

return true;

}

else

{

return false;

}

}

http://www.slideshare.net/IgorShkulipa 21

Арифметические операции

Complex operator +(const Complex& left, const Complex& right)

{

Complex temp;

temp.SetRe(left.GetRe() + right.GetRe());

temp.SetIm(left.GetIm() + right.GetIm());

return temp;

}

Complex operator -(const Complex& left, const Complex& right)

{

Complex temp;

temp.SetRe(left.GetRe() - right.GetRe());

temp.SetIm(left.GetIm() - right.GetIm());

return temp;

}

Complex operator *(const Complex& left, const Complex& right)

{

Complex temp;

double re=left.GetRe()*right.GetRe() – left.GetIm()*right.GetIm();

double im=left.GetRe()*right.GetRe() + left.GetIm()*right.GetIm();

temp.SetRe(re);

temp.SetIm(im);

return temp;

}

http://www.slideshare.net/IgorShkulipa 22

Потоки ввода-вывода

cin и cout - объекты классов istream (от Input Stream - потокввода) и ostream (от Output Stream - поток вывода)

соответственно. Именно для этих классов перегруженыоператоры извлечения и вставки (<< и >>).

Базовым классом является класс ios (от Input/Output Stream -потоковый ввод/вывод). У класса ios довольно много

производных классов.

Наследниками istream и ostream являются ifstream (от InputFile Stream) и ofstream (от Output File Stream). Которые

используются для ввода/вывода в файлы.

Кроме того, есть ещё один класс - fstream (от File Stream -фаловый поток), в котором объединены возможности ifstream

и ofstream. fstream наследуется одновременно и от istream,и от ostream.

http://www.slideshare.net/IgorShkulipa 23

Перегрузка операторов ввода-выводаclass Complex

{

... // Расширение класса Complex

friend ostream operator <<(ostream& out, Complex& c);

friend istream operator >>(istream& in, Complex& c);

}

ostream &operator<<(ostream &out, Complex &c)

{

if (c.GetIm()==0) out<<c.GetRe()<<“\n”;

if (c.GetIm()>0) out<<c.GetRe()<<“+”<<c.GetIm()<<“i”<<“\n”;

if (c.GetIm()<0) out<<c.GetRe()<<“-”<<-c.GetIm()<<“i”<<“\n”;

return out;

}

istream &operator>>(istream &in, Complex &c)

{

double re, im;

in >> re >> im;

c.SetRe(re); c.SetIm(im);

return in;

}

http://www.slideshare.net/IgorShkulipa 24

Результат

#include “complex.h”

void main()

{

Complex c1(1,2);

Complex c2(2,3);

cout << c1;

cout << c2;

cin >> c1;

cin >> c2;

cout << c1+c2;

cout << c1-c2;

cout << c1*c2;

}

http://www.slideshare.net/IgorShkulipa 25

Лабораторная работа №9. Перегрузка операций

Создать класс «Вектор» произвольного размера.

Реализовать методы:

⚫ Конструкторы и деструктор

⚫ Доступа к данным

⚫ Вычисления модуля вектора

Выполнить перегрузку операций:

⚫ Сложения, вычитания, скалярного умножения векторов

⚫ Умножения вектора на скаляр

⚫ Сравнения векторов (==, !=)

⚫ Операции присваивания (=)

⚫ Операцию индексации ( [ ] )

⚫ Операции ввода-вывода

Создать приложение для демонстрации работы класса.

Меню приложения реализовать в виде класса, согласно паттернуSingleton.

http://www.slideshare.net/IgorShkulipa 26

Бонусный слайд №1. Заголовок класса «Вектор»class Vector {

private:

double* _data; int _size;

public:

Vector();

Vector(int);

Vector(double*, int);

Vector(Vector&);

~Vector();

Vector operator = (Vector &v) {//Код оператора}

friend bool operator ==(const Vector& left, const Vector& right);

friend bool operator !=(const Vector& left, const Vector& right);

friend Vector operator +(const Vector& left, const Vector& right);

friend Vector operator -(const Vector& left, const Vector& right);

friend double operator *(const Vector& left, const Vector& right);

friend Vector operator *(const Vector& vect, double scalar);

friend ostream operator <<(ostream& out, Vector& v);

friend istream operator >>(istream& in, Vector& v);

double operator[](int i);

int GetSize();

double* GetData();

void SetSize(int);

void SetData(double*);

}

http://www.slideshare.net/IgorShkulipa 27

Бонусный слайд №2. Операция индексации

double Vector::operator[](int i)

{

if(i<_size)

{

return _data[i];

}

else

{

return NULL;

}

}