← Повернутися до лекцій

Лекція 15: Успадкування (Inheritance)

1. Що таке Успадкування?

Уявіть, що ви створюєте гру. У ній є вороги: "Enemy", "Orc", "Zombie". У всіх є здоров'я (hp), швидкість (speed) і метод attack(). Замість того, щоб писати цей код тричі (для кожного монстра), ми створюємо Базовий клас (Батьківський), який містить спільні характеристики. Інші класи стають Нащадками (Похідними) цього базового класу.

  • Базовий клас (Parent/Base): Містить спільні характеристики.
  • Похідний клас (Child/Derived): Отримує все від батька + додає свої унікальні риси.

2. Синтаксис

Щоб зробити один клас спадкоємцем іншого, використовується двокрапка : після назви класу.

#include <iostream>
using namespace std;

class Animal { // Базовий клас (Base Class)
public:
    void eat() {
        cout << "Я їм..." << endl;
    }
};

// Клас Dog успадковує Animal
class Dog : public Animal {
public:
    void bark() {
        cout << "Гав-гав!" << endl;
    }
};

int main() {
    Dog myDog;
    myDog.eat();  // Цей метод прийшов від Animal!
    myDog.bark(); // А цей метод свій власний.
    return 0;
}

3. Модифікатор доступу protected

Ми знаємо: public — доступно всім, private — тільки самому класу. Успадкування додає третій варіант: protected.

  • private: Навіть діти (похідні класи) НЕ бачать private змінні батька.
  • protected: "Сімейні секрети". Змінні недоступні ззовні (як private), але діти мають до них доступ.
#include <iostream>
using namespace std;

class Device {
protected: // <--- УВАГА
    int batteryLevel; // Доступно для Device і для Phone
public:
    void charge() { batteryLevel = 100; }
};

class Phone : public Device {
public:
    void call() {
        // Ми бачимо batteryLevel, бо він protected
        if (batteryLevel > 0) {
            cout << "Дзвонимо..." << endl;
            batteryLevel--;
        }
    }
};

int main() {
    Phone p;
    p.charge();
    p.call();
    return 0;
}

Якби batteryLevel був private, клас Phone видав би помилку при спробі його змінити.

4. Порядок виклику конструкторів

Це важливе питання на співбесіді! При створенні об'єкта Похідного класу C++ спочатку "будує фундамент".

  1. Спочатку викликається конструктор Базового класу (Батька).
  2. Потім викликається конструктор Похідного класу (Дитини).

При знищенні об'єкта деструктори спрацьовують у зворотному порядку.

Як передати параметри батькові?

Якщо у Батька є конструктор з параметрами, Дитина зобов'язана його викликати через список ініціалізації.

#include <iostream>
#include <string>
using namespace std;

class Person {
public:
    string name;
    Person(string n) { // Конструктор батька вимагає ім'я
        name = n;
    }
};

class Student : public Person {
public:
    int course;
    // Ми передаємо 'n' далі нагору, в конструктор Person
    Student(string n, int c) : Person(n) {
        course = c;
    }
};

int main() {
    Student s("Ivan", 2);
    cout << s.name << " на " << s.course << " курсі" << endl;
    return 0;
}

5. Перевизначення методів (Overriding)

Нащадок може змінити поведінку методу, який отримав від батька. Для цього треба просто оголосити метод з такою самою назвою.

#include <iostream>
using namespace std;

class Animal {
public:
    void speak() { 
        cout << "Якась тварина видає звук" << endl; 
    }
};

class Cat : public Animal {
public:
    // Перевизначаємо (замінюємо) батьківський метод
    void speak() { 
        cout << "Мяу!" << endl; 
    }
};

int main() {
    Cat myCat;
    myCat.speak(); // Виведе "Мяу!" (не "Якась тварина видає звук")
    return 0;
}

Практичні завдання до Лекції 15

Виконайте ці завдання в своєму середовищі розробки.

Завдання 1: Транспорт

  1. Створіть базовий клас Vehicle з полем speed (protected) та методом drive() (виводить "Ідемо зі швидкістю...").
  2. Створіть клас Car, який успадковує Vehicle.
    • Додайте унікальне поле wheels (кількість коліс).
    • Додайте метод honk() (виводить "Біп-біп!").
  3. У main створіть Car, задайте швидкість (через метод або конструктор) і викличте методи drive() та honk().

Завдання 2: Студент та Викладач (Спільне минуле)

  1. Створіть базовий клас Human з полями name та age. Зробіть конструктор, який їх заповнює.
  2. Створіть клас Student, який успадковує Human і додає поле averageScore (середній бал).
  3. Створіть клас Teacher, який успадковує Human і додає поле salary (зарплата).
  4. Напишіть конструктори для Student і Teacher, які передають ім'я та вік у батьківський конструктор Human.
  5. Створіть по одному об'єкту кожного класу і виведіть всю інформацію про них.

Завдання 3: Банківська таємниця (Protected)

  1. Створіть клас Account із полем balance (protected).
  2. Додайте метод deposit(amount) у клас Account для поповнення.
  3. Створіть клас PremiumAccount, який успадковує Account.
  4. У PremiumAccount додайте метод addBonus(). Логіка: якщо на балансі більше 1000 грн, додати ще 50 грн бонусу (змінити balance напряму).
  5. Мета: Переконатися, що клас-нащадок має доступ до protected поля balance, і що цей код працює.