2_3 OOP_C++

Содержание

Слайд 2

Описание класса

class <имя> {
[private:]
<описание скрытых элементов>
public:
<описание доступных элементов>
};
Элементы

Описание класса class { [private:] public: }; Элементы класса – поля и методы.
класса – поля и методы.

Слайд 3

Основные принципы ООП:
- Абстракция данных – выделение наиболее значимых характеристик объектов и

Основные принципы ООП: - Абстракция данных – выделение наиболее значимых характеристик объектов
объединение их в класс;
- Инкапсуляция – сокрытие данных и отдельных методов, необходимых лишь внутреннему состоянию описываемого класса объектов;
- Наследование – частичное или полное заимствование функциональности уже существующего класса при описании нового;
-Полиморфизм – использование объектов с одинаковым интерфейсом без информации о конкретном типе и структуре объектов.

Слайд 4

Абстракция

Пример.
class Cat
{
public:
int32_t age;
double weight;
float length;
};
int main()
{
Cat chonkCat;
chonkCat.age = 10;
chonkCat.weight = 8.0;
chonkCat.length =

Абстракция Пример. class Cat { public: int32_t age; double weight; float length;
52.3f;
}

Слайд 5

Абстракция

Класс Cat объединяет в себе основные свойства типичной кошки или же кота:

Абстракция Класс Cat объединяет в себе основные свойства типичной кошки или же
возраст, вес и длину.
В функции main() создается экземпляр класса Cat, описывающий коренастого кота с определенными свойствами.
Все это позволяет нам создавать объекты, свойства которых будут различны, но при этом выполнять какие-либо универсальные операции над ними в будущем. Таким образом, вводится абстракция над данными, объединяя их в обобщенный класс.
Пример является не самым лучшим, потому что здесь не используется инкапсуляция данных.
В данной ситуации можно было использовать и простую структуру. Однако это не отменяло бы наличие абстрагирования данных.

Слайд 6

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

Применим к имеющемуся коду инкапсуляцию.
class Cat
{
public:
Cat(int age, double weight, float length)
: age(age),

Инкапсуляция Применим к имеющемуся коду инкапсуляцию. class Cat { public: Cat(int age,
weight(weight), length(length) { }
int getHumanAge() { return age * 7; }
protected:
int age;
double weight;
float length;
};
int main()
{
Cat chonkCat(10, 8.0, 52.3f);
std::cout << "chonkCat human age: "
<< chonkCat.getHumanAge() << std::endl;
}

Слайд 7

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

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

Инкапсуляция В данном примере в определенной степени исправлены недостатки предыдущей абстракции. Теперь
выполняется сокрытие данных.
В функции main() вновь создается экземпляр класса Cat, описывающий коренастого кота, однако теперь используется конструктор класса, который позволяет проинициализировать объект.
Основным проявлением инкапсуляции здесь является использование функции getHumanAge(). Это функция использует данные, сокрытые в объекте, для вычисления человеческого аналога возраста кота, который их возвращает. Таким образом, взаимодействия напрямую с полем класса age нет, но при этом остается возможным получить необходимую нам информацию.
Данный наш конструктор просто копирует значения необходимых полей внутрь объекта. Однако в реальной жизни конструкторы чаще всего не просто копируют данные, а используют входные параметры для осуществления внутренней инициализации и сохранения только нужной информации, инкапсулированной внутри класса.

Слайд 8

Наследование

class Shape
{
public:
Shape(int v, int s)
: vertices(v), sides(s) { }
int getNumberOfVertices() {

Наследование class Shape { public: Shape(int v, int s) : vertices(v), sides(s)
return vertices; }
int getNumberOfSides() { return sides; }
private:
int vertices;
int sides;
};
class Triangle : public Shape
{
public:
Triangle(std::array angles)
: Shape(3, 3), angles(angles) {}
private:
std::array angles;
};

Слайд 9

Наследование

class Circle : public Shape
{
public:
Circle(float radius)
: Shape(0, 0), radius(radius) {}
private:
float radius;
};
Класс

Наследование class Circle : public Shape { public: Circle(float radius) : Shape(0,
Shape описывает геометрические фигуры.
Для простоты он содержит только количество вершин
и количество сторон геометрической фигуры.

Слайд 10

Наследование

На основе этого класса, благодаря наследованию, можно создать еще несколько: классы Triangle

Наследование На основе этого класса, благодаря наследованию, можно создать еще несколько: классы
и Circle, описывающие треугольники круг соответственно. Они не имеют специальных методов, хотя могли бы, но расширяют класс Shape, заимствуя представленные поля и методы, а также добавляя свои индивидуальные.
Например, класс Triangle содержит дополнительно информацию о трех углах.
Класс Circle содержит информацию о радиусе круга. При этом оба класса наследника будут содержать методы getNumberOfVertices() и getNumberOfSides(), возвращающие количество вершин и сторон соответственно.

Слайд 11

Спецификаторы доступа

ключевые слова как public, protected и private.
Эти ключевые слова являются спецификаторами

Спецификаторы доступа ключевые слова как public, protected и private. Эти ключевые слова
доступа, которые виляют на наследование и инкапсуляцию.
class A
{
public:
int x;
protected:
int y;
private:
int z;
};
В примере выше есть базовый класс А, содержащий три поля с разными спецификаторами доступа. Если создать объект класса А и попытаться получить доступ к полям, то доступно будет лишь поле x, к другим же полям y и z нельзя обратиться напрямую через экземпляр класса.

Слайд 12

Спецификаторы доступа

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

Спецификаторы доступа Public поля и методы являются доступными как через экземпляры класса,
и классам наследникам;
Protected не доступны через экземпляры класса, однако доступны классам наследникам;
Private являются недоступными ни через экземпляры, ни наследникам.
Также спецификаторы доступа могут быть использованы для изменения спецификаторов наследуемого класса.
Пусть у нас будет три класса, унаследованных от класса А, описанного выше:
class B : public A { };
class C : protected A { };
class D : private A { };

Слайд 13

Спецификаторы доступа
Все эти классы имеют внутренний доступ к полю y базового класса.
При

Спецификаторы доступа Все эти классы имеют внутренний доступ к полю y базового
public наследовании (в случае класса B), спецификаторы доступа наследуемого класса не изменяются.
При protected наследовании (в случае класса C), спецификаторы доступа полей и методов public наследуемого класса изменяются и становятся protected. Таким образом, через экземпляр класса С нельзя будет получить доступ даже к полю x.
При private наследовании (в случае класса D), спецификаторы доступа всех полей и методов наследуемого класса изменяются и становятся private.
Если для описания класса используется ключевое слово struct, то все поля и методы по умолчанию являются public. Если же используется ключевое слово class и не указаны спецификаторы доступа в явном виде, то по умолчанию будет подставлен спецификатор private.

Слайд 14

Полиморфизм
Полиморфизм предполагает, что объекты наследуют и реализуют какой-то обобщенный интерфейс, что позволяет

Полиморфизм Полиморфизм предполагает, что объекты наследуют и реализуют какой-то обобщенный интерфейс, что
работать с ними исключительно через него, при этом не имея информации о том, чем конкретно является объект.
В языке С++ нет такого понятия как интерфейс в чистом виде, в то время как в таких языках как C# или же Java интерфейсы являются встроенным механизмом языка.
Для реализации интерфейсов в С++ используется механизм виртуальных методов класса. Если функция объявлена со спецификатором virtual в начале сигнатуры, то такая функция может быть переопределена в классе наследнике и при этом будет правильно вызываться, даже если работа производится с экземпляром класса наследника лишь через указатель на базовый класс.

Слайд 15

class A
{
public:
virtual void print() { std::cout << "A::print()" << std::endl; }
};
class B

class A { public: virtual void print() { std::cout }; class B
: public A
{
public:
void print() override { std::cout << "B::print()" << std::endl; }
};
int main()
{
A* b = new B();
b->print();
delete b;
return 0;
}

Слайд 16

Полиморфизм
В данном случае при вызове функции print() через указатель на тип A,

Полиморфизм В данном случае при вызове функции print() через указатель на тип
будет вызвана функция, реализованная в классе B.
Соответственно будет выведено “B::print()”. Если бы слова virtual не было, то была бы вызвана функция, реализованная в классе А.
Однако в данном случае А не является интерфейсом в чистом виде. Для полноценной реализации интерфейса необходимо использовать абстрактные классы.
Override используется в классе-потомке, чтобы указать, что функция должна переопределять виртуальную функцию, объявленную в базовом классе.