Лаб. работа “Структурные механизмы языка программирования для реализации полиморфизма в программах”
Цель работы
Изучить механизм виртуальных функций и переопределения методов. Разработать иерархию классов для представления сетевых команд с полиморфным выполнением через единый интерфейс.
Теоретические сведения
Виртуальные функции
Виртуальная функция — функция базового класса, которая может быть переопределена в производных классах. Вызов виртуальной функции через указатель на базовый класс приводит к вызову версии функции того объекта, на который указатель фактически ссылается.
Чисто виртуальные функции и абстрактные классы
Чисто виртуальная функция обозначается = 0. Класс, содержащий хотя бы одну чисто виртуальную функцию, является абстрактным — нельзя создать его объект.
Переопределение (override)
Ключевое слово override проверяет, что функция действительно переопределяет виртуальную функцию базового класса:
Полиморфный вызов через указатель
Виртуальный деструктор
Без виртуального деструктора при delete через указатель на базовый класс вызывается только деструктор базового класса, а не производного — утечка ресурсов.
Задание для выполнения
Разработать иерархию классов для представления сетевых команд с использованием виртуальных функций. Реализовать обработчик, который принимает массив указателей на базовый класс и полиморфно выполняет каждую команду.
Требования к программе
Создать абстрактный базовый класс
AbstractCommand:- защищённые поля:
timestamp(string),status(string, по умолчанию"pending") - чисто виртуальные методы:
void execute(),string getName() const,string getDescription() const - открытые методы:
string getStatus() const,string getTimestamp() const - виртуальный деструктор
- защищённые поля:
Создать производные классы:
LoginCommand— аутентификация на сервере- поля:
username,password(string) execute(): проверяет длину пароля (≥ 6), если успешно —status = "OK", иначе —status = "FAILED: invalid password". Выводит:[LOGIN] Попытка входа: <username> → <status>
- поля:
SendCommand— отправка данных- поля:
recipient(string),data(string),dataSize(int, вычисляется в конструкторе) execute(): еслиdataне пустое иrecipientне пустой —status = "OK", иначе —status = "FAILED: empty data or recipient". Выводит:[SEND] → <recipient> (<dataSize> байт) → <status>
- поля:
ReceiveCommand— получение данных- поля:
sender(string),buffer(string, заполняется при выполнении) execute(): генерирует случайное сообщение отsender.status = "OK". Выводит:[RECV] ← <sender>: <buffer> → <status>
- поля:
DisconnectCommand— отключение от сервера- поля:
reason(string) execute():status = "OK". Выводит:[DISCONNECT] Причина: <reason> → <status>
- поля:
PingCommand— проверка доступности- поля:
targetHost(string),rtt(int, генерируется случайно 1–100 мс) execute():status = "OK". Выводит:[PING] <targetHost> — RTT: <rtt>мс → <status>
- поля:
StatusCommand— запрос статуса сервера- поля:
serverInfo(string, заполняется при выполнении) execute(): генерирует информацию о сервере (имитация).status = "OK". Выводит:[STATUS] <serverInfo> → <status>
- поля:
Создать класс
CommandHandler:- поле:
vector<AbstractCommand*> history - метод
addCommand(AbstractCommand* cmd)— добавляет команду в историю - метод
executeAll()— полиморфно выполняет все команды из истории - метод
showHistory()— выводит все выполненные команды с их статусами - метод
showSuccessful()— выводит только команды со статусом"OK" - метод
clearHistory()— удаляет все команды из истории (с освобождением памяти)
- поле:
В функции
main():- Создать объект
CommandHandler - Добавить команды всех типов с различными параметрами
- Выполнить все команды через
executeAll() - Вывести полную историю
- Вывести только успешные команды
- Очистить историю
- Создать объект
Пример ожидаемого вывода
=== Выполнение команд ===
[LOGIN] Попытка входа: admin → OK
[SEND] → user@192.168.1.5 (13 байт) → OK
[RECV] ← server@10.0.0.1: ACK received → OK
[DISCONNECT] Причина: user request → OK
[PING] 192.168.1.1 — RTT: 23мс → OK
[STATUS] Сервер: online, клиенты: 5, нагрузка: 32% → OK
[LOGIN] Попытка входа: guest → FAILED: invalid password
[SEND] → (0 байт) → FAILED: empty data or recipient
=== История выполнения (8 команд) ===
1. [LOGIN] admin → OK
2. [SEND] user@... → OK
3. [RECV] server@... → OK
4. [DISCONNECT] user req → OK
5. [PING] 192.168.1.1 → OK
6. [STATUS] online → OK
7. [LOGIN] guest → FAILED: invalid password
8. [SEND] (empty) → FAILED: empty data or recipient
=== Успешные команды: 6 из 8 ===
Индивидуальные задания
Вариант 1. FTP-команды
Базовый класс: AbstractFTPCommand (защищённые: timestamp, status; чисто виртуальные: execute(), getName(), getDescription(); виртуальный деструктор). Производные: ConnectCommand (host, port; execute: [CONNECT] Подключение к <host>:<port> → OK), UploadCommand (filename, size; execute: [UPLOAD] <filename> (<size> байт) → OK/FAILED), DownloadCommand (filename; execute: [DOWNLOAD] <filename> → OK/FILE_NOT_FOUND), DeleteCommand (filename; execute: [DELETE] <filename> → OK/DENIED), ListCommand (path; execute: [LIST] <path> → файл1, файл2, ...), ChangeDirCommand (path; execute: [CD] <path> → OK/NOT_FOUND). Обработчик: FTPHandler — addCommand(), executeAll(), showHistory(), showSuccessful(), clearHistory().
Вариант 2. HTTP-команды
Базовый класс: AbstractHTTPCommand (защищённые: timestamp, status; чисто виртуальные: execute(), getName(), getDescription(); виртуальный деструктор). Производные: GetCommand (url; execute: [GET] <url> → 200 OK / 404 Not Found), PostCommand (url, body; execute: [POST] <url> (body: <size> байт) → 201 Created), PutCommand (url, body; execute: [PUT] <url> → 200 OK), DeleteCommand (url; execute: [DELETE] <url> → 204 No Content), HeadCommand (url; execute: [HEAD] <url> → 200 OK (headers only)), OptionsCommand (url; execute: [OPTIONS] <url> → Allow: GET, POST, PUT, DELETE). Обработчик: HTTPHandler — addCommand(), executeAll(), showHistory(), showSuccessful(), clearHistory().
Вариант 3. HTTP-команды
Базовый класс: AbstractHTTPCommand. Производные: GetCommand (url), PostCommand (url, body), PutCommand (url, body), DeleteCommand (url), HeadCommand (url), OptionsCommand (url). Обработчик: HTTPHandler.
Вариант 4. SMTP-команды
Базовый класс: AbstractMailCommand. Производные: HELOCommand (domain), MAILFROMCommand (email), RCPTTOCommand (email), DATACOMMAND (subject, body), QUITCommand, RSETCommand. Обработчик: SMTPHandler.
Вариант 5. DNS-команды
Базовый класс: AbstractDNSCommand. Производные: LookupCommand (domain, type), AddRecordCommand (domain, type, value), RemoveRecordCommand (domain), ListZoneCommand (zone), FlushCacheCommand, StatusCommand. Обработчик: DNSHandler.
Вариант 6. SSH-команды
Базовый класс: AbstractSSHCommand. Производные: ConnectCommand (host, user), ExecuteCommand (command), SCPUploadCommand (local, remote), SCPDownloadCommand (remote, local), TunnelCommand (localPort, remotePort), DisconnectCommand. Обработчик: SSHHandler.
Вариант 7. Команды управления IoT
Базовый класс: AbstractIoTCommand. Производные: ReadSensorCommand (deviceId, type), SetActuatorCommand (deviceId, value), RegisterDeviceCommand (id, type), RemoveDeviceCommand (id), ListDevicesCommand, GetStatusCommand (id). Обработчик: IoTHandler.
Вариант 8. Команды мониторинга
Базовый класс: AbstractMonitorCommand. Производные: CheckCPUCommand (host, threshold), CheckMemoryCommand (host, threshold), CheckDiskCommand (host, path), CheckServiceCommand (host, service), PingCommand (host), TopProcessesCommand (host, count). Обработчик: MonitorHandler.
Вариант 9. Команды управления контейнерами
Базовый класс: AbstractContainerCommand. Производные: StartCommand (name), StopCommand (name), RestartCommand (name), BuildCommand (name, image), RemoveCommand (name), ListCommand. Обработчик: ContainerHandler.
Вариант 10. Команды балансировщика
Базовый класс: AbstractLBCommand. Производные: AddBackendCommand (ip, port), RemoveBackendCommand (ip), SetAlgorithmCommand (algo), EnableBackendCommand (ip), DisableBackendCommand (ip), ShowStatusCommand. Обработчик: LBHandler.
Вариант 11. Команды фаервола
Базовый класс: AbstractFirewallCommand. Производные: AddRuleCommand (from, to, port, action), RemoveRuleCommand (id), ListRulesCommand, EnableRuleCommand (id), DisableRuleCommand (id), ShowStatsCommand. Обработчик: FirewallHandler.
Вариант 12. Команды базы данных
Базовый класс: AbstractDBCommand. Производные: SelectCommand (table, columns, where), InsertCommand (table, values), UpdateCommand (table, set, where), DeleteCommand (table, where), CreateTableCommand (table, columns), DropTableCommand (table). Обработчик: DBHandler.
Вариант 13. Команды чата
Базовый класс: AbstractChatCommand. Производные: JoinCommand (room, username), LeaveCommand (room), SendMessageCommand (room, text), PrivateMessageCommand (to, text), ListRoomsCommand, ListUsersCommand (room). Обработчик: ChatHandler.
Вариант 14. Команды VPN
Базовый класс: AbstractVPNCommand. Производные: ConnectCommand (server, protocol), DisconnectCommand, StatusCommand, ListServersCommand, SetDNSSommand (dns), CheckSpeedCommand (server). Обработчик: VPNHandler.
Вариант 15. Команды файлового сервера
Базовый класс: AbstractFileCommand. Производные: CreateFileCommand (path, size), DeleteFileCommand (path), MoveCommand (from, to), CopyCommand (from, to), SetPermissionsCommand (path, perms), GetInfoCommand (path). Обработчик: FileHandler.
Вариант 16. Команды аутентификации
Базовый класс: AbstractAuthCommand. Производные: RegisterCommand (login, password), LoginCommand (login, password), LogoutCommand, ChangePasswordCommand (old, new), ResetPasswordCommand (email), CheckTokenCommand (token). Обработчик: AuthHandler.
Вариант 17. Команды кэша
Базовый класс: AbstractCacheCommand. Производные: GetCommand (key), SetCommand (key, value, ttl), DeleteCommand (key), FlushCommand, StatsCommand, ExistsCommand (key). Обработчик: CacheHandler.
Вариант 18. Команды очереди сообщений
Базовый класс: AbstractQueueCommand. Производные: PublishCommand (topic, message), SubscribeCommand (topic), UnsubscribeCommand (topic), CreateTopicCommand (name), DeleteTopicCommand (name), ListTopicsCommand. Обработчик: QueueHandler.
Вариант 19. Команды резервного копирования
Базовый класс: AbstractBackupCommand. Производные: FullBackupCommand (source, destination), IncrementalCommand (source, destination), RestoreCommand (backup, target), ScheduleCommand (source, interval), ListBackupsCommand, VerifyCommand (backup). Обработчик: BackupHandler.
Вариант 20. Команды CI/CD
Базовый класс: AbstractCICommand. Производные: BuildCommand (project, branch), TestCommand (project, suite), DeployCommand (project, env), RollbackCommand (project, version), StatusCommand (project), ListProjectsCommand. Обработчик: CIHandler.
Порядок выполнения
- Создать проект C++ в Qt Creator (CMake).
- Определить абстрактный класс
AbstractCommand. - Реализовать все производные классы команд с переопределением
execute(),getName(),getDescription(). - Реализовать класс
CommandHandlerс полиморфным выполнением. - В
main()создать команды, выполнить, вывести результаты. - Скомпилировать, запустить, сохранить скриншоты.
Контрольные вопросы
- Что такое виртуальная функция и как она реализуется в C++ (vtable)?
- Что такое чисто виртуальная функция? Можно ли создать объект абстрактного класса?
- Что означает ключевое слово
override? Чем отличается переопределение от перегрузки? - Почему деструктор базового класса должен быть виртуальным? Что произойдёт, если он не виртуальный?
- Что такое статический и динамический полиморфизм? Приведите примеры.
- Можно ли вызвать чисто виртуальную функцию из конструктора базового класса?
- Какова роль указателя на базовый класс при работе с коллекцией объектов производных классов?
- В чём преимущество паттерна «Команда» для сетевых приложений?
Содержание отчёта
- Тема, цель и задание лабораторной работы.
- Диаграмма иерархии классов команд.
- Текст программы с комментариями.
- Скриншоты результата выполнения программы.
- Ответы на контрольные вопросы.