- Объяснять понятия класса и объекта
- Писать класс с полями и методами
- Писать конструкторы со списком инициализации и деструктор
- Защищать данные с помощью
publicиprivate
В игре сотни персонажей: у каждого есть имя, здоровье и уровень, и каждый умеет двигаться и атаковать. Хранить всё это в отдельных переменных и функциях — быстро запутаешься. C++ позволяет создать собственный тип — класс. Класс объединяет данные и функции, которые с ними работают.
Класс и объект
Класс — чертёж нового типа: он описывает, какие данные (поля) и какие функции (методы) будут у объектов. Объект — конкретный экземпляр, созданный по этому классу, так же как x — переменная типа int, когда пишешь int x;.
#include <iostream>
#include <string>
class Student {
public:
std::string name;
int grade = 0;
void introduce() const {
std::cout << name << " is in grade " << grade << '\n';
}
};
int main() {
Student a;
a.name = "Aysel";
a.grade = 8;
Student m;
m.name = "Murad";
m.grade = 9;
a.introduce();
m.introduce();
return 0;
}Aysel is in grade 8 Murad is in grade 9
- К членам обращаются через точку:
a.name,a.introduce(). - У каждого объекта свои данные:
aиmсозданы из одного класса, но имена и классы у них разные. constпосле метода означает, что он не изменяет объект; компилятор это проверяет.
Конструкторы и деструктор
Конструктор — особый метод, который вызывается автоматически при создании объекта. Его имя совпадает с именем класса, и у него нет типа возвращаемого значения. Конструкторы, как и обычные функции, можно перегружать. Значения полям лучше всего задавать в списке инициализации — после двоеточия, перед телом: : width_(w), height_(h).
#include <iostream>
class Rectangle {
public:
Rectangle() : width_(1), height_(1) {}
Rectangle(int w, int h) : width_(w), height_(h) {}
int area() const { return width_ * height_; }
int perimeter() const { return 2 * (width_ + height_); }
private:
int width_;
int height_;
};
int main() {
Rectangle tile;
Rectangle room(4, 3);
std::cout << "Tile area: " << tile.area() << '\n';
std::cout << "Room area: " << room.area() << '\n';
std::cout << "Room perimeter: " << room.perimeter() << '\n';
return 0;
}Tile area: 1 Room area: 12 Room perimeter: 14
Деструктор вызывается при уничтожении объекта: его имя начинается с ~ (~Logger). Локальный объект уничтожается, когда выходит из своей области видимости — своих фигурных скобок. Именно на этом построен принцип RAII из прошлого урока: ресурс берётся в конструкторе и освобождается в деструкторе.
#include <iostream>
#include <string>
class Logger {
public:
Logger(const std::string& name) : name_(name) {
std::cout << "Start " << name_ << '\n';
}
~Logger() {
std::cout << "End " << name_ << '\n';
}
private:
std::string name_;
};
int main() {
Logger a("A");
{
Logger b("B");
}
std::cout << "Main done\n";
return 0;
}Start A Start B End B Main done End A
b уничтожается в конце внутреннего блока, а a — в конце main.public, private и инкапсуляция
Если бы любой код мог напрямую менять баланс банковского счёта, кто-нибудь по ошибке записал бы туда отрицательное число. Инкапсуляция скрывает данные и разрешает доступ к ним только через методы с проверками. Для этого есть спецификаторы доступа: члены public видны отовсюду, а члены private — только собственным методам класса.
#include <iostream>
class BankAccount {
public:
BankAccount(int balance) : balance_(balance) {}
void deposit(int amount) {
if (amount > 0) {
balance_ += amount;
}
}
bool withdraw(int amount) {
if (amount <= 0 || amount > balance_) {
return false;
}
balance_ -= amount;
return true;
}
int balance() const { return balance_; }
private:
int balance_;
};
int main() {
BankAccount acc(100);
acc.deposit(50);
std::cout << std::boolalpha << acc.withdraw(500) << '\n';
std::cout << acc.withdraw(30) << '\n';
std::cout << "Balance: " << acc.balance() << " AZN\n";
// acc.balance_ = 1000000; // error: balance_ is private
return 0;
}false true Balance: 120 AZN
| Спецификатор | Кто имеет доступ |
|---|---|
public | любой код |
private | только методы самого класса |
protected | методы самого класса и производные классы (следующий урок) |
Главное
- Класс — чертёж нового типа, объект — его конкретный экземпляр.
- К членам обращаются через точку;
const-метод не меняет объект. - Конструктор вызывается автоматически при создании объекта, деструктор (
~Имя) — при уничтожении. - Задавать значения полям лучше всего в списке инициализации.
privateскрывает данные, аpublic-методы дают к ним контролируемый доступ — это инкапсуляция.
Проверь себя
Вопросов: 10. Каждый правильный ответ приносит XP.