- •1. Краткие теоретические сведения
- •1.1. Объектно-ориентированный подход-Бузюков
- •1.2. Этапы разработки ооп систем
- •1.3. Декомпозиция
- •1.5. Концепции ооп
- •1.6. Синтаксис объявления класса
- •1.7. Методы класса
- •1.8. Объявление объектов
- •1.9. Конструктор
- •1.10. Деструктор
- •1.11. Инкапсуляция
- •1.12. Полиморфизм
- •1.13. Указатель this
- •1.14. Статические члены класса
- •1.15. Дружественные функции и классы
- •1.16. Вложенные классы
- •1.17. Элементы класса
- •1.17.1. Данные-элементы
- •1.17.2. Элементы-функции
- •1.17.3. Доступ к данным-элементам
- •1.17.4. Вызов функций-элементов
- •1.17.5. Указатели на компоненты-функции.
- •2. Задание
- •2.4.1.2. Пример для варианта 30
- •2.4.1.2.1. Разработка алгоритма решения.
- •2.4.1.2.2. Описание структуры класса.
- •2.4.1.2.2.1. Описание полей класса.
- •2.4.1.2.2.2. Функции-аксессоры.
- •2.4.1.3. Программа
- •2.4.1.4. Тестирование
- •2.4.2. Задание 2. Простейшие классы и объекты
- •2.4.2.1. Условие задания
- •2.4.2.2. Пример
- •2.4.2.3. Программа
- •2.4.2.4. Тестирование
- •2.4.3. Задание 3. Простейший класс. Объединение данных и методов
- •2.4.3.1. Условие задания
- •2.4.3.2. Пример
- •2.4.3.3. Программы
- •2.4.3.3.1. Первый принцип инкапсуляции: объединение данных и методов
- •2.4.3.3.2. Второй принцип инкапсуляции: защита от внешнего вмешательства
- •2.4.3.3.3. Независимость интерфейса от реализации
- •2.4.3.3.4. Конструктор, деструктор
- •2.4.3.3.5. Определение методов вне класса
- •2.4.3.3.6. Конcтантные поля, методы и объекты
- •2.4.3.4. Тестирование
- •2.4.4. Задание 4. Пользовательский класс
- •2.4.4.1. Условие задания
- •2.4.4.2. Методические указания.
- •1. Пример определения класса.
- •2. Пример реализации конструктора с выдачей сообщения.
- •3. Выводы
- •4. Требование к отчету
- •4. Краткие теоретические сведения.
- •5. Вопросы для самоконтроля
- •Литература
- •1. Краткие теоретические сведения 2
- •1.1. Объектно-ориентированный подход-Бузюков 2
1.11. Инкапсуляция
Инкапсуляция – это принцип ООП, объединяющий в одном классе данные и методы, манипулирующие этими данными и защищающие данные класса от внешнего воздействия.
Обратимся к примеру из жизни, чтобы понять смысл этого принципа. Представьте себе, что в вашу квартиру пришел знакомый и переставил вашу мебель по своему усмотрению, не считаясь с вашим вкусом. Скорее всего, вам это не понравится, и вы перестанете приглашать этого человека в свой дом. Если же вы для перестановки мебели позовете помощников, то сначала объясните им, что и как надо переставить, тогда в результат их работы вы получите квартиру, обустроенную так, как это нужно вам.
Класс также защищает свое состояние (значения свойств) от несанкционированного изменения, это реализуется с помощью раздела класса private. Включенные в private свойства доступны только этому объекту, поэтому не могут быть изменены другими объектами. Для доступа к свойствам в раздел класса public включаются методы. Методы проверяют, возможно ли такое изменение состояния объекта под влиянием других объектов, и только после этого изменяют значения переменных состояния. Если переход в новое состояние невозможен, методы оставляют объект в прежнем состоянии.
Пример 20.18.
Изменим пример 20.7 с принтером. Предположим, во время профилактики вычислительной системы у принтера было отключено электропитание. Естественно, в этом случае наши попытки что-то напечатать ни к чему не приведут. Учтем это в нашей модели принтера. Добавим свойство is_on, отражающее подключение к принтеру электрического питания (0 – включено, 1 – выключено). Тогда состояние принтера определяется комбинацией значений двух свойств – is_on и status (табл. 20.2).
Таблица 20.2
Допустимые состояния принтера
is_on |
status |
Сообщение на экране |
0 |
0 |
Принтер включен |
1 |
0 |
Принтер включен Состояние: готов к работе |
1 |
1 |
Принтер включен Состояние: печатает |
При этом класс представляется в виде:
class Printer
{
char model[15];
int year;
int status;
int is_on; //Принтер включен (0 – нет,1 – да)
public:
Printer(char* _model, int _year);
void on_off(); //Включение/выключение питания
void set_print();
void stop_print();
void show();
};
//Конструктор
Printer :: Printer(char* _model, int _year)
{
strcpy(model, _model);
year=_year;
status=0;
is_on=0; //Принтер отключен по умолчанию
}
void Printer :: on_off()
{
//Метод моделирует нажатие кнопки включения
//питания:если оно выключено, то произойдет
//включение, и наоборот;
//одновременно при любых переключениях питания //принтер оказывается в состоянии готовности
//и печать не ведет
is_on=!is_on;
status=0;
}
void Printer :: set_print()
{
If (is_on) status=1; //Принтер будет печатать,
//если он включен
}
void Printer :: stop_print()
{
If (status) status=0; //Принтер остановится,
//если он до того печатал
}
void Printer :: show()
{
cout << "Модель: " << model << "Год выпуска: " << year << endl;
if (is_on)
{
cout << "Принтер включен";
if (status) cout << "Состояние: печатает";
else cout << "Состояние: готов к работе";
}
else cout << "Принтер выключен";
cout << endl;
}
Полный текст программы для примера 20.18:
//Пример 20.18
#include <iostream.h>
#include <conio.h>
class Printer
{
private:
char* model;//указатель на строку, которая будет
//содержать название модели принтера
//и разместится в динамической памяти
int year; //год выпуска
int status; //состояние принтера
int is_on; //Принтер включен (0 - нет,1 - да)
public:
//Конструктор с параметрами
Printer(char* _model, int _year);
//Деструктор
~Printer();
void init_printer(char* _model, int _year,int _is_on);
void on_off(); //Включение/выключение питания
void set_print();
void stop_print();
void show();
};
void Printer::init_printer(char* _model,int _year,int _is_on)
{
strcpy(model,_model); //инициализация свойства model
year=_year; //инициализация свойства year
is_on=_is_on;
status=0; //начальное состояние - готов к печати
}
void Printer :: on_off()
{
//Метод моделирует нажатие кнопки включения
//питания:если оно выключено, то произойдет
//включение, и наоборот;
//одновременно при любых переключениях питания
//принтер оказывает-ся в состоянии готовности
//и печать не ведет
is_on=!is_on;
status=0;
}
void Printer :: set_print()
{
if (is_on) status=1; //Принтер будет печатать,
//если он включен
}
void Printer :: stop_print()
{
if (status) status=0; //Принтер остановится,
//если он до того печатал
}
void Printer :: show()
{
cout << "Модель: " << model << " Год выпуска: " << year << endl;
if (is_on)
{
cout << "Принтер включен";
if (status) cout << "Состояние: печатает";
else cout << "Состояние: готов к работе";
}
else cout << "Принтер выключен";
cout << endl;
}
//Конструктор с параметрами
Printer :: Printer(char* _model, int _year)
{
int len=strlen(_model); //Определение длины
//строки
//Выделение памяти в динамической области
//для размещения строки и символа '\0'
model=new char[len+1];
strcpy(model, _model);
year=_year;
status=0;
is_on=0; //Принтер отключен по умолчанию
}
//Деструктор
Printer :: ~Printer()
{
//Освобождение динамической памяти
delete[] model;
//Присваивание указателю значения пустого
//указателя, обязательно в Visual C++
model = NULL;
}
int main()
{
//Создание первого объекта
Printer printer1("HP5P",2004);
printer1.show();
//Создание второго объекта
Printer printer2("Canon_BJC250",2000);
printer2.show();
cout << "\nНажмите любую клавишу..." ;
getch();
return 0;
}
Тестирование:
Класс запрещает прямой доступ к своим переменным состояния, поэтому не удастся реализовать недопустимое состояние is_on=0, status=1. Методы set_print(), stop_print(), on_off(), предоставляющие доступ к свойствам объекта, реализованы так, что также исключают это состояние объекта. В этом и заключается смысл понятия инкапсуляции.
Полный текст модифицированной программы для примера 20.18:
//Пример 20.18m
#include <iostream.h>
#include <conio.h>
class Printer
{
private:
char* model;//указатель на строку, которая будет
//содержать название модели принтера
//и разместится в динамической памяти
int year; //год выпуска
int status; //состояние принтера
int is_on; //Принтер включен (0 - нет,1 - да)
public:
//Конструктор с параметрами
Printer(char* _model, int _year,int _is_on);
//Деструктор
~Printer();
void init_printer(char* _model, int _year,int _is_on);
void on_off(); //Включение/выключение питания
void set_print();
void stop_print();
void show();
};
void Printer::init_printer(char* _model,int _year,int _is_on)
{
strcpy(model,_model); //инициализация свойства model
year=_year; //инициализация свойства year
is_on=_is_on;
status=0; //начальное состояние - готов к печати
}
void Printer :: on_off()
{
//Метод моделирует нажатие кнопки включения
//питания:если оно выключено, то произойдет
//включение, и наоборот;
//одновременно при любых переключениях питания
//принтер оказывает-ся в состоянии готовности
//и печать не ведет
is_on=!is_on;
status=0;
}
void Printer :: set_print()
{
if (is_on) status=1; //Принтер будет печатать,
//если он включен
}
void Printer :: stop_print()
{
if (status) status=0; //Принтер остановится,
//если он до того печатал
}
void Printer :: show()
{
cout << "Модель: " << model << " Год выпуска: " << year << endl;
if (is_on)
{
cout << " Принтер включен";
if (status) cout << " Состояние: печатает";
else cout << " Состояние: готов к работе";
}
else cout << " Принтер выключен";
cout << endl;
}
//Конструктор с параметрами
Printer :: Printer(char* _model, int _year,int _is_on)
{
int len=strlen(_model); //Определение длины
//строки
//Выделение памяти в динамической области
//для размещения строки и символа '\0'
model=new char[len+1];
strcpy(model, _model);
year=_year;
status=0;
is_on=_is_on; //Принтер отключен по умолчанию
}
//Деструктор
Printer :: ~Printer()
{
//Освобождение динамической памяти
delete[] model;
//Присваивание указателю значения пустого
//указателя, обязательно в Visual C++
model = NULL;
}
int main()
{
//Создание первого объекта
Printer printer1("HP5P",2004,0);
printer1.show();
//Создание второго объекта
Printer printer2("Canon_BJC250",2000,1);
printer2.show();
cout << "\nНажмите любую клавишу..." ;
getch();
return 0;
}
Тестирование: