Главная страница
Навигация по странице:

  • Лабораторная работа №1 «Множественное наследование. Виртуальное наследование»Вариант 17

  • Краткие теоретические сведения

  • Индивидуальное задание

  • Отчёт. Лабораторная работа 1 Множественное наследование. Виртуальное наследование Вариант 17


    Скачать 1.08 Mb.
    НазваниеЛабораторная работа 1 Множественное наследование. Виртуальное наследование Вариант 17
    Дата12.09.2022
    Размер1.08 Mb.
    Формат файлаdocx
    Имя файлаОтчёт.docx
    ТипЛабораторная работа
    #673787

    Министерство образования Республики Беларусь

    БЕЛОРУССКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ

    ИНФОРМАТИКИ И РАДИОЭЛЕКТРОНИКИ

    Инженерно-экономический факультет

    Кафедра экономической информатики

    Лабораторная работа №1

    «Множественное наследование.

    Виртуальное наследование»

    Вариант 17


    Выполнил:

    студент группы 172303

    Бовкун Максим Игоревич


    Проверил:

    старший преподаватель

    кафедры ЭИ

    Салапура М.Н,



    Минск 2022

    Цель работы: изучить принципы и получить практические навыки при использовании множественного наследования; рассмотреть случаи, когда необходимо использовать виртуальное наследование.

    Задачи: освоить принцип множественного наследования, его проблемы и способы его разрешения с помощью множественного наследования.
    Краткие теоретические сведения
    Множественное наследование происходит, когда подкласс имеет два или более суперкласса. Проблема ромба (Diamond problem)- классическая проблема в языках, которые поддерживают возможность множественного наследования. Эта проблема возникает когда классы B и C наследуют A, а класс D наследует B и C. Вся проблема в том, что создаётся 2 базовых класса вместо одного, то есть схема наследования выглядит так, как на рисунке 1.

    Рисунок 1 – Проблема множественно наследования

    Для разрешения этой проблемы используется виртуальное наследование. Для это нужно при наследовании после режима доступа указать ключевое слово virtual и тогда наследование диаграмма наследование будет выглядеть так, как на рисунке 2.

    Рисунок 2 – Виртуальное наследование

    В данной работе память под объекты выделяется автоматически. Чтобы проверять тип на соответствии с другим типом. В языке программирования C++ операция dynamic_cast преобразует тип данных (указатель или ссылку) вниз по иерархии наследования (из типа-предка в тип-потомок), с проверкой с помощью динамической идентификации типа данных, корректно ли приведение. Этот тип преобразования называется "нисходящим приведением типа", поскольку при нем указатель перемещается вниз по иерархии классов: от базового класса к производному классу.  При работе со ссылками при невозможности преобразования типа будет сгенерировано исключение std::bad_cast. Таким образом, оператор dynamic_cast обнаруживает сходство в процедуре приведения типа с таким языком программирования как Java, в отличие от Си, в котором не выполняется проверка корректности приведения типа во время выполнения программы.
    Индивидуальное задание
    Построить иерархию классов согласно схеме наследования, приведенной на рисунке ниже по предметной области «Графический пользовательский интерфейс». Каждый класс должен содержать необходимые конструкторы и методы работы с полями классов. Функция main() должна иллюстрировать работу с массивами объектов всех созданных классов. При необходимости самостоятельно добавить классы для реализации множественного наследования.

    Рисунок 3 – Задание

    Прежде чем приступить к разработке программы необходимо построить более детальную диаграмму, в которой будут изображены основные методы и атрибуты. Диаграмма классов UML была построена в программе Modelio 4.1 и изображена на рисунке 4.

    Рисунок 4 – Диаграмма классов UML
    Код программы:
    Control.h:

    #pragma once

    #include

    #include

    class Control

    {

    private:

    std::string id;

    int height;

    int width;

    virtual void polymorhic() = 0;

    protected:

    Control(std::string id="", int height = 0, int width = 0) {

    this->id = id;

    this->height = height;

    this->width = width;

    }

    public:

    std::string getId() {

    return id;

    }
    int getHeight() {

    return height;

    }
    int getWidth() {

    return width;

    }
    void setId(std::string id) {

    this->id = id;

    }
    void setHeight(int height) {

    this->height = height;

    }
    void setWidth(int width) {

    this->width = width;

    }
    };
    Button.h:

    #pragma once

    #include"Control.h"

    #include
    class Button: public virtual Control

    {

    public:

    enum TextColor { RED, GREEN, WHITE, YELLOW };

    private:

    Button::TextColor color;

    std::string textButton;
    virtual void polymorhic() {}

    public:

    Button(Button::TextColor color = WHITE, std::string text="Nothing", std::string id = "", int height = 0, int width = 0) : Control(id, height, width) {

    this->color = color;

    this->textButton = text;

    }

    std::string getTextColor() {

    switch (color)

    {

    case RED:

    return "Красный";

    case GREEN:

    return "Зелёный";

    case WHITE:

    return "Белый";

    case YELLOW:

    return "Жёлтый";

    };

    }
    void setColor(Button::TextColor color) {

    this->color = color;

    }
    std::string getText() {

    return textButton;

    }

    void setText(std::string newText) {

    this->textButton = newText;

    }


    };
    Image.h:

    #pragma once

    #include"Control.h"

    class Image:public virtual Control

    {

    public:

    enum StretchStyle { FULL_SIZE, TO_ONE_SIDE };// enumination to assign style of stretching image
    enum StretchDirection { VERTICAL_DIRECTION, HORIZONTAL_DIRECTION };// enumination to assign direction of stretching image
    enum ImageType { CAT, DOG, PUMA };

    private:

    Image::StretchDirection direction;

    Image::StretchStyle style;

    Image::ImageType picture;
    virtual void polymorhic() {}

    public:

    Image(Image::StretchDirection direction = Image::StretchDirection::HORIZONTAL_DIRECTION, Image::StretchStyle style = FULL_SIZE, Image::ImageType picture=Image::ImageType::CAT , std::string id = "", int height = 0, int width = 0) : Control(id, height, width) {

    this->direction = direction;

    this->style = style;

    this->picture = picture;

    }
    std::string getDirection() {

    switch (direction)

    {

    case Image::StretchDirection::VERTICAL_DIRECTION:

    return "Вертикальное направление";

    case Image::StretchDirection::HORIZONTAL_DIRECTION:

    return "Горизонатальное направление";

    };

    }

    std::string getStyle() {

    switch (style)

    {

    case FULL_SIZE:

    return "Растяжение на полный экран";

    case TO_ONE_SIDE:

    return "Растяжение на одну сторону";

    };

    }
    Image::StretchStyle getEnumStyle() {

    return this->style;

    }
    void setStyle(Image::StretchStyle style) {

    this->style = style;

    }

    void setDirection(Image::StretchDirection direction) {

    this->direction = direction;

    }

    void setPicture(Image::ImageType picture) {

    this->picture = picture;

    }
    std::string getPicture() {

    switch (picture)

    {

    case CAT:

    return "Котёнок";

    case DOG:

    return "Собачка";

    case PUMA:

    return "Пума";

    };

    }

    };
    ImageButton.h:
    #pragma once

    #include"Image.h"

    #include"Button.h"

    class ImageButton: public Image,public Button
    {

    virtual void polymorhic() {}

    };
    WorkingWithMenu.h:
    #pragma once

    #define MAX_CONTROL_SIZE 1200

    #define MIN_CONTROL_SIZE 200

    #include

    #include

    #include

    #include"TransformString.h"

    #include"ImageButton.h"

    class WorkingWithMenu

    {

    private:

    std::valarray firstMenu;

    std::valarray inputControlProperty;

    std::valarray inputImageType;

    std::valarray inputImageStretch;

    std::valarray inputImageStretchDirection;

    std::string inputButtonText;

    std::valarrayinputButtonColor;

    std::string errorMessage;
    Control* control = nullptr;
    void initField() {

    firstMenu = {

    "Выберите элемент графического управления, прообраз которого хотите создать",

    "1)Картинка",

    "2)Кнопка",

    "3)Картинка-кнопка"

    };
    inputControlProperty = {

    "Введите высоту элемента управления в пикселях(200-1200): ",

    "Введите ширину элемента управления в пикселях(200-1200): ",

    "Введите ID элемента управления: "

    };
    inputImageType = {

    "Выберите тип картинки: ",

    "1)Котёнок",

    "2)Собачка",

    "3)Пума",

    };
    inputImageStretch = {

    "Веберите стиль растяжения: ",

    "1)Изображение полностью на весь элемент управления",

    "2)Растяжение только на одну сторону",

    };
    inputImageStretchDirection = {

    "Веберите сторону расстяжения: ",

    "1)По горизонтали",

    "2)По вертикали"

    };
    inputButtonText = "Введите текст кнопки: ";
    inputButtonColor = {

    "Выберите цвет картинки",

    "1)Красный",

    "2)Зелёный",

    "3)Белый",

    "4)Жёлтый"

    };
    errorMessage = "Неверный выбор, повторите ещё раз...";

    }
    void printStringArray(std::valarray& strings) {

    std::cout << "+";

    for (int i = 0; i < 90; i++) {

    std::cout << "-";

    }

    std::cout << "+\n";

    for (int i = 0; i < strings.size(); i++) {

    std::cout << "|";

    std::cout.width(90);

    std::cout << std::left << strings[i];

    std::cout << "|\n";

    }

    std::cout << "+";

    for (int i = 0; i < 90; i++) {

    std::cout << "-";

    }

    std::cout << "+\n";

    }
    std::string printFiledToEnterChoice() {

    std::cout << "Ваш ответ -=> ";

    std::string string;

    std::getline(std::cin, string);

    return string;

    }
    void settingControlProperty() {

    for (int i = 0; i < 2; i++) {

    int enter = 0;

    TransformString transform;

    while (enter > MAX_CONTROL_SIZE || enter < MIN_CONTROL_SIZE) {

    std::cout << inputControlProperty[i] << std::endl;

    enter = transform.getString(printFiledToEnterChoice());

    if (enter > MAX_CONTROL_SIZE || enter < MIN_CONTROL_SIZE) {

    std::cout << errorMessage;

    }
    }

    if (i == 0) {

    control->setHeight(enter);

    }

    else control->setWidth(enter);
    }

    std::cout << inputControlProperty[2];

    control->setId(printFiledToEnterChoice());

    }
    void settingImageProperty() {

    Image* image = dynamic_cast(control);

    switch (readAndCheckingInput(inputImageType))

    {

    case 1:

    image->setPicture(Image::ImageType::CAT);

    break;

    case 2:

    image->setPicture(Image::ImageType::DOG);

    break;

    case 3:

    image->setPicture(Image::ImageType::PUMA);

    break;

    }

    switch (readAndCheckingInput(inputImageStretch))

    {

    case 1:

    image->setStyle(Image::StretchStyle::FULL_SIZE);

    break;

    case 2:

    image->setStyle(Image::StretchStyle::TO_ONE_SIDE);

    switch (readAndCheckingInput(inputImageStretchDirection))

    {

    case 1:

    image->setDirection(Image::StretchDirection::HORIZONTAL_DIRECTION);

    break;

    case 2:

    image->setDirection(Image::StretchDirection::VERTICAL_DIRECTION);

    break;

    }

    break;

    }
    }
    void settingButtonProperty() {

    Button* button = dynamic_cast(control);

    switch (readAndCheckingInput(inputButtonColor))

    {

    case 1:

    button->setColor(Button::TextColor::RED);

    break;

    case 2:

    button->setColor(Button::TextColor::GREEN);

    break;

    case 3:

    button->setColor(Button::TextColor::WHITE);

    break;

    case 4:

    button->setColor(Button::TextColor::YELLOW);

    break;

    }
    std::cout << inputButtonText << std::endl;

    button->setText(printFiledToEnterChoice());

    }
    int readAndCheckingInput(std::valarray& strings) {

    int enter = 0;

    TransformString transform;

    while (enter > strings.size()-1 || enter < 1) {

    printStringArray(strings);

    enter = transform.getString(printFiledToEnterChoice());

    if (enter > strings.size()-1 || enter < 1) {

    std::cout << errorMessage << std::endl;

    }

    }

    return enter;

    }
    public:

    Control* run() {

    switch (readAndCheckingInput(firstMenu))

    {

    case 1:

    control = new Image();

    settingControlProperty();

    settingImageProperty();
    break;

    case 2:

    control = new Button();

    settingControlProperty();

    settingButtonProperty();

    break;

    case 3:

    control = new ImageButton();

    settingControlProperty();

    settingImageProperty();

    settingButtonProperty();

    break;

    default:

    break;

    }

    return control;
    }

    WorkingWithMenu() {

    initField();

    }

    };
    TransoformString.h:

    #pragma once

    #include

    #include

    class TransformString

    {

    public:

    int getString(std::string string) {

    int number = 0;

    int i = 0;

    for (; i < string.size(); i++) {

    if (!isdigit(string[i]))

    {

    break;

    }

    }

    if (i == string.size()) {

    number = atoi(string.c_str());

    }

    else number = -1;

    return number;

    }

    };

    OutputControl.h:

    #pragma once

    #include"ImageButton.h"

    #include
    class OutputControl

    {

    private:

    Control* control;

    std::ostream* out;

    void printControl() {

    *out << "\tШирина и высота: " << control->getWidth() << "*" << control->getHeight() << std::endl;

    *out << "\tID объекта: " << control->getId()<
    }

    void printImage(Image * image) {

    *out << "\tТип картинки: "<getPicture()<
    *out << "\tСтиль растяжение картинки: "<< image->getStyle()<
    if (image->getEnumStyle() == image->TO_ONE_SIDE) {

    *out << "\tНаправление, к которой картинка будет растянута: "<getDirection()<
    }

    }

    void printButton(Button* button) {
    *out << "\tЦвет текста: "<< button->getTextColor()<
    *out << "\tТекст кнопки: "<getText()<
    }

    void printImageButton(ImageButton* imageButton) {

    printImage(imageButton);

    printButton(imageButton);

    }

    public:

    OutputControl(Control* control, std::ostream* out) {

    this->control = control;

    this->out = out;

    }

    void printInfo() {

    *out << "Вы выбрали следующие параметры: ";

    if (dynamic_cast(control)) {

    *out << "Картинка-кнопка:\n";

    printControl();

    printImageButton(dynamic_cast(control));

    }

    else if (dynamic_cast(control)) {

    *out << "Кнопка:\n";

    printControl();

    printButton(dynamic_cast(control));

    }

    else {

    *out << "Картинка:\n";

    printControl();

    printImage(dynamic_cast(control));

    }

    }

    };
    Main.cpp:
    #include

    #include

    #include
    #include"ImageButton.h"

    #include"WorkingWithMenu.h"

    #include"OutputControl.h"

    #include

    int main()

    {

    SetConsoleCP(1251);

    SetConsoleOutputCP(1251);

    WorkingWithMenu* menu=new WorkingWithMenu();

    Control* control=menu->run();

    system("cls");

    std::ofstream fileOut("Info.txt", std::ios::ate);

    if (!fileOut.is_open()) {

    std::cout << "Ошибка в открытие файла Info.txt"<
    exit(1);

    }

    OutputControl output(control, &std::cout);

    output.printInfo();
    OutputControl output2(control, &fileOut);

    output2.printInfo();

    std::cout << "\nДанные также записаны в файл Info.txt...\n";

    fileOut.close();

    return 0;

    }

    // create printing photo using SFML
    Заключение: были изучены принципы и получены практические навыки при использовании множественного наследования; рассмотрены случаи, когда необходимо использовать виртуальное наследование.


    написать администратору сайта