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

Лекція 13: Класи та Об'єкти (Основи ООП)

У попередній лекції ми вивчили struct. Виникає питання: навіщо нам ще й class, якщо структури вже вміють об'єднувати дані?

Відповідь: Безпека та Контроль. У структурах всі дані відкриті "нарозхрист". Будь-хто може написати student.grade = 1000, навіть якщо максимальна оцінка 100. Класи дозволяють це заборонити.

1. Що таке Клас і Об'єкт?

  • Клас — це креслення, шаблон або форма (наприклад, креслення автомобіля BMW).
  • Об'єкт — це конкретний екземпляр, створений за цим кресленням (конкретна машина BMW у вашому гаражі).

2. Синтаксис та Специфікатори доступу

Головна відмінність класу від структури — це права доступу. У класах з'являються ключові слова:

  1. public (Публічний): Доступно всім ззовні (як вітрина магазину).
  2. private (Приватний): Доступно тільки самому класу (як сейф у кабінеті директора).

За замовчуванням у class усе є private.

class BankAccount {
private:
    double balance; // Гроші сховані. Ззовні змінити не можна!
public:
    string ownerName; // Ім'я доступне всім
    // Методи (функції всередині класу)
    void showBalance() {
        // Всередині класу ми маємо доступ до private змінних
        cout << "Баланс: " << balance << endl;
    }
};

3. Методи класу

Класи містять не тільки дані (змінні), а й дії (функції). Ці функції називаються методами. Вони працюють з даними конкретного об'єкта.

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

class Cat {
public:
    string name;
    void meow() {
        cout << name << " каже: Мяу!" << endl;
    }
};

int main() {
    Cat myCat;
    myCat.name = "Barsik";
    myCat.meow(); // Виведе: Barsik каже: Мяу!
    return 0;
}

4. Інкапсуляція (Getters та Setters)

Принцип ООП: "сховай дані, покажи методи". Змінні робимо private, щоб не можна було записати неправильне значення (наприклад, вік -5 років). Щоб керувати цими private змінними, використовують спеціальні public методи:

  • Setter: Для встановлення значень з перевіркою.
  • Getter: Для отримання значень.

Приклад: Розумна людина

#include <iostream>
using namespace std;

class Person {
private:
    int age; // Сховано від зовнішнього світу
public:
    // Сеттер: Дозволяє змінити вік, але ТІЛЬКИ правильно
    void setAge(int newAge) {
        if (newAge > 0 && newAge < 120) {
            age = newAge;
        } else {
            cout << "Помилка! Некоректний вік." << endl;
        }
    }
    // Геттер: Дозволяє дізнатися вік
    int getAge() {
        return age;
    }
};

int main() {
    Person student;
    // student.age = -10; // ПОМИЛКА! Це private поле.
    student.setAge(-5); // Виведе повідомлення про помилку
    student.setAge(20); // Успішно запише 20
    cout << "Студенту " << student.getAge() << " років." << endl;
    return 0;
}

5. Чому це круто?

Сценарій: У гравця є health.

Проблема з public health: Якщо health — це public змінна, будь-яка частина коду може випадково написати health = -1000, і гра зламається.

Рішення з private health та методом takeDamage: Якщо healthprivate і керується методом типу takeDamage(int damage), ви можете всередині методу реалізувати логіку, наприклад: "Якщо здоров'я впало до 0, запустити анімацію програшу."

Висновок: Інкапсуляція дає вам повний контроль над вашими даними.

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

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

Завдання 1: Простий клас "Телефон"

  1. Створіть клас Phone з полями:
    • brand (бренд) - public
    • model (модель) - public
    • price (ціна) - public
  2. Додайте метод printInfo(), який виводить: "Це телефон [Brand] [Model], який коштує [Price] грн."
  3. У функції main створіть об'єкт класу Phone, заповніть його дані та викличте метод printInfo().

Завдання 2: Прямокутний захист (Інкапсуляція)

  1. Створіть клас Rectangle з полями:
    • width (ширина) - private
    • height (висота) - private
  2. Додайте методи:
    • setWidth(int value) — сеттер для width. Якщо передано від'ємне значення, встановіть width = 0 або виведіть повідомлення про помилку.
    • setHeight(int value) — сеттер для height. Якщо передано від'ємне значення, встановіть height = 0 або виведіть повідомлення про помилку.
    • getArea() — повертає площу прямокутника (width * height).
  3. У функції main протестуйте реалізацію, спробувавши встановити від'ємну ширину.

Завдання 3: Банківський рахунок (Логіка)

  1. Створіть клас BankAccount з полями:
    • accountNumber - public
    • balance - private, тип double
  2. Додайте методи:
    • deposit(double amount) — додає amount до балансу. Переконайтеся, що amount не від'ємний.
    • withdraw(double amount) — знімає amount з балансу. Важливо: якщо баланс менший за суму зняття, операцію скасувати і вивести на екран "Недостатньо коштів".
    • getBalance() — повертає поточний баланс рахунку.