1. Модуль 3: Основные понятия объектно-ориентированного
программирования.
Темы лекции: Продолжение введения в ООП.Перегрузка
операций.
Практическое задание: Перегрузка операций.
Тренер: Игорь Шкулипа, к.т.н.
C++ Базовый. Занятие 9
3. http://www.slideshare.net/IgorShkulipa 3
Дружественные функции
Дружественные функции – это функции, объявленные вне класса,
но имеющие доступ к закрытым и защищенным полям данного класса
Дружественная функция объявляется внутри класса с модификатором
friend
Дружественные функции не являются членами класса, поэтому им не
передается указатель this
Дружественные операции, как и дружественные функции, могут
иметь доступ к приватным и защищенным методам класса
class Class1
{
friend void FriendMethod();
};
4. http://www.slideshare.net/IgorShkulipa 4
Дружественные классы
Некоторым классам может понадобиться доступ к закрытым данным друг
друга.
В этом случае необходимо объявить дружественный класс внутри
определения класса
class Class1;
class Class2
{
friend class Class1;
private:
int data;
};
Дружественная связь между классами является самой сильной.
Реализации классов оказываются связанными, что противоречит
принципу инкапсуляции.
(!) Не используйте дружественные классы до тех пор, пока их
использование не окажется единственным способом решения задачи
5. http://www.slideshare.net/IgorShkulipa 5
Статические данные и методы
Для каждого объекта создается своя собственная копия членов данных.
Для некоторых классов было бы удобно использовать данные, общие
для всех экземпляров данного класса (например, строковое
представление имени класса или константы, общие для всех
экземпляров класса, область видимости которых должна быть
ограничена методами класса)
Такие поля и методы называют статическими и объявляют при помощи
ключевого слова static
class Class1
{
static void StaticMethod();
};
6. http://www.slideshare.net/IgorShkulipa 6
Особенности статических методов
◦ Статические методы не получают указатель this.
◦ Статические методы могут обращаться только к статическим данным
класса.
◦ Статические методы могут вызывать только статические методы
(либо нестатические, если им передается указатель или ссылка на
объект класса).
◦ Статические методы имеют доступ к закрытым и защищенным полям
и методам класса, через экземпляры классов.
◦ Доступ к статическим методам и данным класса осуществляется по
имени класса (создавать экземпляр не требуется).
7. http://www.slideshare.net/IgorShkulipa 7
Применение статических методов
◦ Паттерн «одиночка» (singleton).
◦ Объект с глобальным доступом, существующий в программе в
единственном экземпляре.
◦ Методы и данные, характерные для класса в целом, а не для
отдельных его экземпляров.
◦ Создание классов-утилит
8. http://www.slideshare.net/IgorShkulipa 8
Вложенное объявление классов
Язык C++ позволяет разместить объявление одного класса (или другого
типа данных) внутри объявления другого.
Это полезно, когда вложенный тип данных используется только внешним
классом, или совместно с ним.
Использование вложенного класса может происходить двумя способами:
⚫ Из методов внешнего класса – по имени вложенного класса
⚫ Снаружи – при помощи указания имени внешнего класса:
ExternalClass::InternalClass
9. 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();
}
11. 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<<"Method1n";}
void Method2(){cout<<"Method2n";}
private:
Singleton(){}
static Singleton* _instance;
};
Singleton::_instance=NULL;
int main()
{
Singleton* singleton = Singleton::GetInstance();
singleton->Method1();
singleton->Method2();
}
12. http://www.slideshare.net/IgorShkulipa 12
Применение Singleton
Применяется, когда нужен только один экземпляр класса.
Например для хранения глобальной конфигурации системы,
для ведения логов, связи с базой данных и т.д.
Основное преимущество перед глобальными переменными в
том, что экземпляр класса создается не при инициализации
программы, а по первому требованию.
14. http://www.slideshare.net/IgorShkulipa 14
Для чего нужна перегрузка операций
Для некоторых типов данных естественными может оказаться
использование операций над базовыми типами:
⚫ += и + для конкатенации строк
⚫ -- и ++ для итераторов
⚫ арифметические операции для векторов и комплексных
чисел
⚫ [] для векторов и матриц
⚫ = для классов с собственным конструктором копирования
⚫ операции сравнения для строк и других типов
15. http://www.slideshare.net/IgorShkulipa 15
Перегрузка операций
Для пользовательских типов данных C++ позволяет задать
собственные операции
⚫ Некоторые из них всегда определяются внутри класса
⚫ =, +=, -=, *= и т.д.
⚫ Некоторые – снаружи (операции, в которых применяются
базовые типы).
⚫ Некоторые – где угодно.
Синтаксис:
<тип> operator <О>(параметры)
22. http://www.slideshare.net/IgorShkulipa 22
Потоки ввода-вывода
cin и cout - объекты классов istream (от Input Stream - поток
ввода) и ostream (от Output Stream - поток вывода)
соответственно. Именно для этих классов перегружены
операторы извлечения и вставки (<< и >>).
Базовым классом является класс ios (от Input/Output Stream -
потоковый ввод/вывод). У класса ios довольно много
производных классов.
Наследниками istream и ostream являются ifstream (от Input
File Stream) и ofstream (от Output File Stream). Которые
используются для ввода/вывода в файлы.
Кроме того, есть ещё один класс - fstream (от File Stream -
фаловый поток), в котором объединены возможности ifstream
и ofstream. fstream наследуется одновременно и от istream,
и от ostream.
23. 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;
}
25. http://www.slideshare.net/IgorShkulipa 25
Лабораторная работа №9. Перегрузка операций
Создать класс «Вектор» произвольного размера.
Реализовать методы:
⚫ Конструкторы и деструктор
⚫ Доступа к данным
⚫ Вычисления модуля вектора
Выполнить перегрузку операций:
⚫ Сложения, вычитания, скалярного умножения векторов
⚫ Умножения вектора на скаляр
⚫ Сравнения векторов (==, !=)
⚫ Операции присваивания (=)
⚫ Операцию индексации ( [ ] )
⚫ Операции ввода-вывода
Создать приложение для демонстрации работы класса.
Меню приложения реализовать в виде класса, согласно паттерну
Singleton.