Menu
Coddy logo textTech

Спецификаторы доступа в C++

Часть раздела Объектно-ориентированное программирование путешествия по C++ на Coddy. Урок 34 из 104.

C++ предоставляет три спецификатора access, которые определяют, кто может получить доступ к членам class: public, protected и private. Они составляют основу инкапсуляции.

class Account {
public:
    std::string ownerName;      // Доступен из любого места
    
protected:
    double interestRate;        // Доступен в этом классе и производных классах
    
private:
    double balance;             // Доступен только внутри этого класса
};

Public members могут быть доступны из anywhere — inside the class, из derived classes и из внешнего кода. Private members являются наиболее ограниченными: accessible только внутри самого class. Protected находится между ними — для внешнего мира он действует как private, но derived classes могут получать доступ к этим members.

class Account {
private:
    double balance;
    
public:
    Account() : balance(0) {}
    
    void deposit(double amount) {
        balance += amount;    // OK - внутри класса
    }
};

int main() {
    Account acc;
    acc.deposit(100);         // OK - deposit является public
    // acc.balance = 500;     // ERROR - balance является private
}

По умолчанию все members в классе являются private, если спецификатор не указан. Это побуждает вас явно решать, что следует сделать доступным. Обычно data members делают private и предоставляют public методы для безопасного взаимодействия с ними.

challenge icon

Задание

Легко

Давайте создадим простую систему управления сотрудниками, демонстрирующую, как спецификаторы доступа определяют, кто и к чему может получить доступ. Вы создадите class, в котором одни данные полностью закрыты, некоторые доступны потенциальным производным классам, а некоторые открыты для всех.

Для организации кода вы создадите два файла:

  • Employee.h: определите Employee class, использующий все три спецификатора доступа для надлежащей защиты данных:
    • Открытый: имя employee (string). К нему можно получить доступ anywhere
    • Защищённый: employee department (string): доступен внутри class и производным class, но не снаружи
    • Закрытый: зарплата employee (double): доступна только внутри самого class
    • Конструктор, принимающий имя, department и зарплату для инициализации всех трёх members
    • Открытый method getSalary(), возвращающий значение закрытой зарплаты
    • Открытый method getDepartment(), возвращающий значение защищённого department
    • Открытый method giveRaise(double amount), увеличивающий зарплату на указанную сумму (только если amount положителен)
    • Открытый method displayInfo(), выводящий information employee в формате: "Name: <name>, Department: <department>, Salary: $<salary>"
  • main.cpp: продемонстрируйте работу спецификаторов доступа, взаимодействуя с объектом Employee. Считайте имя employee, department и зарплату из input (три отдельные строки), затем:
    • Создайте Employee с введёнными значениями
    • Выведите имя employee напрямую, получив доступ к открытому member: "Direct access - Name: <name>"
    • Выведите department с помощью getter: "Via getter - Department: <department>"
    • Выведите зарплату с помощью getter: "Via getter - Salary: $<salary>"
    • Дайте employee повышение на 5000.0
    • Выведите "After raise:"
    • Вызовите displayInfo(), чтобы показать обновлённую information

Форматируйте все значения зарплаты с двумя десятичными знаками, используя std::fixed и std::setprecision(2) из <iomanip>. Преобразуйте input зарплаты из строки в double с помощью std::stod().

Главная идея заключается в том, что, хотя из main можно напрямую получить доступ к name, напрямую получить доступ к department или зарплате нельзя. Необходимо использовать открытые getter methods. Это инкапсуляция в действии: class контролирует способы доступа к своим данным и их изменения.

Попробуйте сами

#include <iostream>
#include <string>
#include <iomanip>
#include "Employee.h"

using namespace std;

int main() {
    // Считать ввод
    string name;
    string department;
    string salaryStr;
    
    getline(cin, name);
    getline(cin, department);
    getline(cin, salaryStr);
    double salary = stod(salaryStr);
    
    // Установить точность для вывода зарплаты
    cout << fixed << setprecision(2);
    
    // TODO: Создать объект Employee с входными значениями
    
    // TODO: Вывести имя сотрудника, обращаясь напрямую к публичному члену
    // Format: "Direct access - Name: <name>"
    
    // TODO: Вывести отдел с помощью метода-геттера
    // Format: "Via getter - Department: <department>"
    
    // TODO: Вывести зарплату с помощью метода-геттера
    // Format: "Via getter - Salary: $<salary>"
    
    // TODO: Дать сотруднику повышение на 5000.0
    
    // TODO: Вывести "After raise:"
    
    // TODO: Вызвать displayInfo() для отображения обновлённой информации
    
    return 0;
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Онлайн-компилятор C++