Основы информатики Классы Заикин Олег Сергеевич

advertisement
Основы информатики
Классы
Заикин Олег Сергеевич
zaikin.icc@gmail.com
Объектно-ориентированное
программирование

Инкапсуляция - скрытие деталей реализации,
обеспечение доступности главного путем помещения
всего мешающего, второстепенного в некую условную
капсулу (чёрный ящик).

Наследование позволяет создавать иерархию
объектов, в которой объекты-потомки наследуют все
свойства своих предков. Свойства при наследовании
повторно не описываются. Кроме унаследованных,
потомок обладает собственными свойствами. Объект в
C++ может иметь сколько угодно потомков и предков.

Полиморфизм - возможность определения единого по
имени действия, применимого ко всем объектам
иерархии, причем каждый объект реализует это
действие собственным способом.
Класс
Объектно-ориентированное программирование основано
на понятии класса.
Класс – абстрактный тип данных в объектноориентированном программировании.
Объект – экземпляр класса. Класс задает формат
объекта.
Класс – абстракция, которая реально не существует, пока
не будет создан объект этого класса.
Класс
Объявляя класс, Вы задаете данные и код, который
выполняется над данными.
Простой класс может содержать только данные или только
код, но обычно содержится и то и другое.
Класс в итоге определяется как список своих членов, а
именно полей (свойств) и методов/функций/процедур.
Класс
Объявление класса начинается с ключевого слова class и
синтаксически подобно объявлению структуры.
По умолчанию члены класса являются закрытыми (private),
т.е. к ним могут получить доступ только функции этого же
класса. Никакие другие части программы этого не могут.
Это одно из проявлений инкапсуляции – можно управлять
доступом к определенным элементам данных. Для
открытости нужно использовать ключевое слово public.
class <имя> {
private:
<описание скрытых извне членов класса>
public:
<описание доступных извне членов класса>
};
Поля класса
Поля класса:
• могут иметь любой тип, кроме типа этого же класса
(но могут быть указателями или ссылками на этот
класс);
• могут быть описаны с модификатором const.
Инициализация полей при описании не допускается.
Тело класса определяет отдельную область видимости.
Наличие в двух разных классах членов с одинаковыми
именами – не ошибка, эти имена относятся к разным
областям видимости.
Функции класса
Функции (методы) класса объявляются в его теле.
Функции класса отличается от обычных функций
следующим:
функции класса имеют право доступа как к открытым, так
и к закрытым членам класса, тогда как обычным
функциям доступны лишь открытые. Конечно, функции
одного класса, как правило, не имеют доступа к данным
другого класса.
Пример класса
Пример. Класс очередь (queue)
class queue {
int q[100];
int sloc, rloc;
void init();
void qput(int i);
int qget();
};
Почему класс queue бесполезен?
Эквивалентно
class queue {
private:
int q[100];
int sloc, rloc;
void init();
void qput(int i);
int qget();
};
Класс
class queue {
int q[100];
int sloc, rloc;
public:
void init();
void qput(int i);
int qget();
};
Теперь к функциям init(), qput() и qget() доступ открытый.
Хотя бы к одной функции класса должен быть открытый
доступ, иначе невозможно что-либо сделать с полями
класса.
Класс
После создания объект имеет собственную копию данных,
которые составляют класс. Объект занимает определенную
область памяти.
Чтобы получить доступ к открытому члену класса используется
оператор «точка», как и при работе со структурами.
К закрытым членам класса так обратиться нельзя.
Пример
queue Q1, Q2; // объявление двух объектов класса queue
Q1.init(); // вызов открытой функции
Q1.sloc = 3; // ошибка компиляции - попытка обращения к
закрытому члену класса.
Класс
В объявлении класса содержатся только прототипы функций.
Чтобы реализовать функцию, необходимо указать к какому
классу она принадлежит. Для этого перед именем функции нужно
поставить имя класса и “::”.
“::” - оператор разрешения области видимости, он квалифицирует
имя члена класса вместе с именем его класса.
Пример
void queue :: qput(int i)
{
if (sloc == 100) {
cout << “Очередь заполнена” << endl;
return;
}
q[sloc++] = i;
}
Класс
Различные классы могут использовать одинаковые имена своих
членов. С помощью оператора “::” компилятор определит, к
какому классу он относится.
Для вызова из функции класса другой функции этого же класса
оператор “.” не требуется. Аналогично для обращения к полям
класса.
Пример
void queue :: init()
{
rloc = sloc = 0; // указывать область видимости не нужно
}
Класс
Обычно описание класса помещают в заголовочный файл
(расширение *.h), а реализацию функций класса – в файл c
расширением *.cpp. Называться файлы должны одинаково.
Файл queue.h
class queue {
int sloc, rloc;
public:
void init(int i);
};
Файл queue.cpp
#include “queue.h”;
void queue :: init()
{
rloc = sloc = 0;
}
Пример программы
Пример программы
Закрытые элементы
Если rloc и sloc будут public, к чему это может привести?
// функция возвращает текущее количество элементов в очереди
int queue :: size()
{
return sloc - rloc;
}
Присваивание объектов
Если есть два объекта одного класса, то один можно присвоить
другому. По умолчанию данные поразрядно копируются, в том
числе закрытые.
queue Q1. Q2;
Q1.init();
// Q1.rloc == 0, Q2.rloc неопределен
Q2 = Q1;
// Q1.rloc == 0, Q2.rloc == 0
Если в классе есть указатель, что произойдет при
копировании объектов?
Присваивание объектов
class myclass {
int *a;
};
myclass x, y;
x.a = new int[2];
y = x;
Если в классе есть переменная-указатель, что произойдет
при копировании объектов?
Конструктор
Конструктор – функция, которая автоматически вызывается при
создании объекта. Имя конструктора совпадает с именем класса.
Используется для инициализации части данных.
Если программист не указал ни одного конструктора, компилятор
создает его автоматически. Такой конструктор вызывает
конструкторы по умолчанию для полей класса и конструкторы по
умолчанию базовых классов.
Например для класса queue при инициализации переменным rloc
и sloc нужно присвоить нулевые значения.
В рассмотренном ранее примере инициализация выполняется в
функции init().
Конструктор
Пример
class queue {
int q[100];
int sloc, rloc;
public:
queue(); // конструктор
void qput(int i);
int qget();
};
queue :: queue()
{
sloc = rloc = 0;
}
queue Q1, Q2; // создано 2 объекта, у каждого вызван конструктор
Деструктор
Деструктор – функция, которая вызывается при разрушении
объекта. Нужен для освобождения ранее выделенной для
объекта памяти или других действий при разрушении объекта.
Имя деструктора – это имя конструктора, перед которым стоит
символ ~
class queue {
int q[100];
int sloc, rloc;
public:
queue(); // конструктор
~queue(); // деструктор
void qput(int i);
int qget();
};
Деструктор
Деструктор
вызывается
автоматически,
когда
объект
выходит из области видимости:
 для локальных объектов — при выходе из блока, в котором
они объявлены;
 для глобальных — как часть процедуры выхода из main;
 для объектов, заданных через указатели, деструктор
вызывается неявно при использовании операции delete.
Деструктор
Деструктор можно вызвать явным образом путем указания
полностью уточненного имени, например:
queue *q; ...
q -> ~queue();
Деструктор:
 не имеет аргументов и возвращаемого значения;
 Если деструктор явным образом не определен,
компилятор автоматически создает пустой деструктор.
Download