Наследование классов в C++ [Урок 13] | Разработка игровых платформ
  1. Доброго времени суток. В связи с появлением спамеров, активация функций новых пользователей (Создавать темы, писать сообщения), теперь будет только после проверки администратором! Для регистрации отписываемся в лс, в вк. vk.com/tehnik777 (Пишем только с реальных страниц)
    Скрыть объявление

Наследование классов в C++ [Урок 13]

Тема в разделе "С++/С#, HTML, PHP, JavaScript, XML...", создана пользователем Zloo, 6 ноя 2016.

Обсуждение темы Наследование классов в C++ [Урок 13] в разделе С++/С#, HTML, PHP, JavaScript, XML... на форуме zetta-forum.ru.

  1. Zloo

    Zloo Администратор Команда форума

    Регистрация:
    31 окт 2016
    Сообщения:
    265
    Симпатии:
    158
    Баллы:
    43
    Пол:
    Мужской
    Сайт:
    https://zetta-forum.ru
    VK:
    https://vk.com/tehnik777
    Наследование классов в C++ [Урок 13]


    Наследование позволяет избежать дублирования лишнего кода при написании классов. Пусть в базе данных ВУЗа должна храниться информация о всех студентах и преподавателях. Представлять все данные в одном классе не получится, поскольку для преподавателей нам понадобится хранить данные, которые для студента не применимы, и наоборот.

    Создание базового класса

    Для решения этой задачи создадим базовый класс human, который будет описывать модель человека. В нем будут храниться имя, фамилия и отчество.

    Создайте файл human.h:


    Код:
    // human.h
    #ifndef HUMAN_H_INCLUDED
    #define HUMAN_H_INCLUDED
    
    #include <string>
    #include <sstream>
    
    class human {
        public:
            // Конструктор класса human
            human(std::string last_name, std::string name, std::string second_name)
            {
                this->last_name = last_name;
                this->name = name;
                this->second_name = second_name;
            }
    
            // Получение ФИО человека
            std::string get_full_name()
            {
                std::ostringstream full_name;
                full_name << this->last_name << " "
                    << this->name << " "
                    << this->second_name;
                return full_name.str();
            }
    
        private:
            std::string name; // имя
            std::string last_name; // фамилия
            std::string second_name; // отчество
    };
    
    #endif // HUMAN_H_INCLUDED
    

    Наследование от базового класса

    Теперь создайте новый класс student, который будет наследником класса human. Поместите его в файл student.h


    Код:
    // student.h
    #ifndef STUDENT_H_INCLUDED
    #define STUDENT_H_INCLUDED
    
    #include "human.h"
    #include <string>
    #include <vector>
    
    class student : public human {
        public:
            // Конструктор класса Student
            student(
                std::string last_name,
                std::string name,
                std::string second_name,
                std::vector<int> scores
            ) : human(
                last_name,
                name,
                second_name
            ) {
                this->scores = scores;
            }
    
            // Получение среднего балла студента
            float get_average_score()
            {
                // Общее количество оценок
                unsigned int count_scores = this->scores.size();
                // Сумма всех оценок студента
                unsigned int sum_scores = 0;
                // Средний балл
                float average_score;
    
                for (unsigned int i = 0; i < count_scores; ++i) {
                    sum_scores += this->scores;
                }
    
                average_score = (float) sum_scores / (float) count_scores;
                return average_score;
            }
    
        private:
            // Оценки студента
            std::vector<int> scores;
    };
    #endif // STUDENT_H_INCLUDED
    



    Функция get_average_score вычисляет среднее арифметическое всех оценок студента. Все публичные свойства и методы класса human будут доступны в классе student.

    Конструктор базового класса

    Для того, чтобы инициализировать конструктор родительского класса (в нашем случае — это сохранение имени, фамилии и отчества ученика), используется следующий синтаксис:


    Код:
    // Конструктор класса Student
    student(
        // аргументы конструктора текущего класса
    ) : human(
        // инициализация конструктора родительского класса
    ) {
        // инициализация конструктора текущего класса
    }
    

    В конструктор класса human мы передаем инициалы человека, которые сохраняются в экземпляре класса. Для класса students, нам необходимо задать еще и список оценок студента. Поэтому конструктор students принимает все аргументы конструктора базового класса, а также дополнительные аргументы для расширения функционала:


    Код:
    // Конструктор класса Student
    student(
        std::string last_name,
        std::string name,
        std::string second_name,
        std::vector<int> scores
    ) : human(
        last_name,
        name,
        second_name
    ) {
        this->scores = scores;
    }
    

    Список оценок студента хранится в векторе.

    Создание объекта класса student

    Реализуем пользовательский интерфейс для работы с классом student.


    Код:
    // main.cpp
    
    #include <iostream>
    #include <vector>
    
    #include "human.h"
    #include "student.h"
    
    int main(int argc, char* argv[])
    {
    
        // Оценки студента
        std::vector<int> scores;
    
        // Добавление оценок студента в вектор
        scores.push_back(5);
        scores.push_back(3);
        scores.push_back(2);
        scores.push_back(2);
        scores.push_back(5);
        scores.push_back(3);
        scores.push_back(3);
        scores.push_back(3);
        scores.push_back(3);
    
        // Создание объекта класса student
        student *stud = new student("Петров", "Иван", "Алексеевич", scores);
    
        // Вывод полного имени студента (используется унаследованный метод класса human)
        std::cout << stud->get_full_name() << std::endl;
        // Вывод среднего балла студента
        std::cout << "Средний балл: " << stud->get_average_score() << std::endl;
    
        return 0;
    }
    

    В этом примере мы написали программу, которая создает объект класса student, сохраняя в нем его имя, фамилию, отчество и список оценок.

    После инициализации объекта, происходит вывод полного имени студента с помощью функции get_full_name. Эта функция была унаследована от базового класса human.

    Затем программа вычислияет средний балл студента и выводит его на экран. Этим занимается функция get_average_score, которую мы описали внутри класса student.

    Мы реализовали часть функционала для нашей базы данных института (я конечно утрирую, когда оперирую столь серьезными высказываниями про настоящую базу данных :)

    Создание класса-наследника teacher

    Нужно создать еще один класс, в котором будут храниться данные преподавателей. Дадим ему название — teacher. Как вы уже поняли, мы не будем описывать все методы этого класса с нуля, а просто унаследуем его от класса human. Тогда, не нужно будет реализовывать хранение имени, фамилии и отчества препода. Это уже есть в базовом классе human.

    Создайте файл teacher.h:


    Код:
    // teacher.h
    #ifndef TEACHER_H_INCLUDED
    #define TEACHER_H_INCLUDED
    
    #include "human.h"
    #include <string>
    
    class teacher : public human {
        // Конструктор класса teacher
        public:
            teacher(
                std::string last_name,
                std::string name,
                std::string second_name,
                // Количество учебных часов за семетр у преподавателя
                unsigned int work_time
            ) : human(
                last_name,
                name,
                second_name
            ) {
                this->work_time = work_time;
            }
    
            // Получение количества учебных часов
            unsigned int get_work_time()
            {
                return this->work_time;
            }
    
        private:
            // Учебные часы
            unsigned int work_time;
    };
    
    #endif // TEACHER_H_INCLUDED
    

    У класса teacher появилось новое свойство — количество учебных часов, отведенное преподавателю на единицу времени (семестр). Весь остальной функционал наследуется от базового класса human. Если бы мы писали все с нуля, то одинакового кода бы получилось в разы больше, и его поддержка усложнилась бы на порядок.

    Создание объекта класса teacher

    Изменим содержимое файла main.cpp, чтобы проверить работу класса teacher.


    Код:
    #include <iostream>
    
    #include "human.h"
    #include "teacher.h"
    
    int main(int argc, char* argv[])
    {
    
        // Количество учебных часов преподавателя
        unsigned int teacher_work_time = 40;
    
        teacher *tch = new teacher("Васильков", "Петр", "Сергеевич", teacher_work_time);
    
        std::cout << tch->get_full_name() << std::endl;
        std::cout << "Количество часов: " << tch->get_work_time() << std::endl;
    
        return 0;
    }
    

    Если сборка программы прошла без ошибок, то результат работы программы будет таким:

    [​IMG]

    Можно таким же образом создать класс, в котором будут храниться данные обслуживающего персонала или руководящего состава. Наследование используют, когда у каждой группы объектов есть общие параметры, но для каждой из этих групп нужно хранить более кастомные данные.

    Также, мы можем создать класс, который будет описывыть студента заочной формы обучения. Его мы унаследовали бы от класса student, добавив какие-либо дополнительные данные.

    В класс human можно добавить еще больше свойств, которые будут описывать данные, имеющиеся у любого человека. Например, номер паспорта, дату рождения, прописку и место проживания.

    Подобный подход позволяет в разы уменьшить дублирование кода в реальных проектах, и упросить его поддержку.

    Когда нужно использовать конструктор

    Если у класса много свойств — их совсем не обязательно задавать в конструкторе. Для сохранения отдельных свойств класса используют set-функции. Например, для сохранения номера паспорта, можно создать публичный метод set_passport_number(std::string number), который будет принимать значение свойства и сохранять его в объекте, через переменную this.
     

Поделиться этой страницей