Наследование классов в С++.



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

Основная информация о наследовании классов, которую важно знать:

  • Наследование — это определение производного класса, который может обращаться ко всем элементам и методам базового класса за исключением тех, которые находятся в поле private;
  • Производный класс еще называют потомком или подклассом, а базовый — родитель или надкласс;
  • Синтаксис определения производного класса:
    class   Имя_Производного_Класса    :    спецификатор доступа    Имя_Базового_Класса   { /*код*/ } ;
  • Производный класс имеет доступ ко всем элементам и методам базового класса, а базовый класс может использовать только свои собственные элементы и методы.
  • В производном классе необходимо явно определять свои конструкторы, деструкторы и перегруженные операторы присваивания из-за того, что они не наследуются от базового класса.

Как же происходит наследование?

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

// 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[i];
            }

            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.

Конструкторы и деструкторы при наследовании

Как базовый, так и производный классы могут иметь конструкторы и деструкторы. Если и у базового и у производного классов есть конструкторы и деструкторы, то конструкторы выполняются в порядке наследования, а деструкторы – в обратном порядке. То есть если А – базовый класс, В – производный из А, а С – производный из В (А-В-С), то при создании объекта класса С вызов конструкторов будет иметь следующий порядок:

  • конструктор класса А
  • конструктор класса В
  • конструктор класса С.

Вызов деструкторов при удалении этого объекта произойдет в обратном порядке:

  • деструктор класса С
  • деструктор класса В
  • деструктор класса А.

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

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

Один класс может наследовать атрибуты двух и более классов одновременно. Для этого используется список базовых классов, в котором каждый из базовых классов отделен от других запятой. Общая форма множественного наследования имеет вид:

class имя_порожденного_класса: список базовых классов
{
...
};

В следующем примере класс Z наследует оба класса X и Y:

#include <iostream.h>
class X {
protected:
int a;
public:
void make_a(int i) { a = i; }
};
class Y {
protected:
int b;
public:
void make_b(int i) { b = i; }
};
// Z наследует как от X, так и от Y
class Z: public X, public Y {
public:
int make_ab() { return a*b; }
};
int main()
{
Z i;
i.make_a(10);
i.make_b(12);
cout << i .make_ab();
return 0;
}

Поскольку класс Z наследует оба класса X и Y, то он имеет доступ к публичным и защищенным членам обоих классов X и Y.

На сегодня наш урок окончен и в конце хочу сказать, что наследование — это классная возможность языка С++. Она помогает экономить массу времени на написание и отладку кода с нуля. Вместо этого мы можем использовать уже готовый и отлаженный код и подстраивать его под новые задачи. При этом новая программа будет занимать намного меньше строк, что значительно улучшит её читабельность.

1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (Пока оценок нет)
Загрузка...

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Chinese (Traditional)EnglishJapaneseRussianUkrainian

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: