Что такое модификатор доступа private в C++?

Ответ

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

Основная цель — инкапсуляция: Сокрытие внутренней реализации класса и защита его внутреннего состояния от некорректного или несанкционированного изменения извне. Это позволяет изменять реализацию класса, не ломая код, который его использует.

Пример:

#include <iostream>
#include <string>

class BankAccount {
private:
    // Внутреннее состояние — скрыто от внешнего мира
    std::string accountNumber;
    double balance;
    bool isActive;

    // Внутренний служебный метод — тоже скрыт
    void logTransaction(const std::string& type, double amount) {
        std::cout << "[" << accountNumber << "] " << type << ": " << amount << 'n';
    }

public:
    // Публичный интерфейс для взаимодействия
    BankAccount(const std::string& accNum, double initialDeposit)
        : accountNumber(accNum), balance(initialDeposit), isActive(true) {}

    void deposit(double amount) {
        if (amount > 0 && isActive) {
            balance += amount;
            logTransaction("DEPOSIT", amount);
        }
    }

    bool withdraw(double amount) {
        if (amount > 0 && isActive && balance >= amount) {
            balance -= amount;
            logTransaction("WITHDRAW", amount);
            return true;
        }
        return false;
    }

    double getBalance() const { // Геттер — безопасный доступ к private-полю
        return balance;
    }

    void deactivate() {
        isActive = false;
        std::cout << "Account " << accountNumber << " deactivated.n";
    }
};

int main() {
    BankAccount myAccount("ACC123", 1000.0);

    myAccount.deposit(500.0); // OK: публичный метод
    myAccount.withdraw(200.0); // OK: публичный метод
    std::cout << "Current balance: " << myAccount.getBalance() << 'n'; // OK: геттер

    // myAccount.balance = 1000000; // ОШИБКА КОМПИЛЯЦИИ: прямой доступ к private-полю
    // myAccount.logTransaction("HACK", 9999); // ОШИБКА: вызов private-метода

    return 0;
}

Важные детали:

  • Различие между class и struct: В class по умолчанию все члены являются private. В struct по умолчанию все члены являются public.
  • Наследование: При приватном наследовании (class Derived : private Base) все члены базового класса (и public, и protected) становятся private в производном классе. Это редко используется и обычно означает отношение "реализовано посредством" (implementation inheritance), а не "является" (is-a).
  • Дружественные объявления (friend): Позволяют предоставить доступ к private-членам конкретным внешним функциям или классам, нарушая инкапсуляцию в контролируемой точке. Следует использовать осмотрительно.

Ответ 18+ 🔞

Слушай, давай разберём эту штуку с private в C++, а то некоторые думают, что это просто слово для красоты. Это, блядь, основа основ, ёпта! Представь, что твой класс — это твоя хата. А private — это твоя спальня, куда ты не пускаешь кого попало. Туда можно только тебе и твоим самым близким друзьям (это friend-объявления, но о них позже). Все остальные — соседи, гости, продавцы из магнита — стоят в коридоре (это public) и общаются с тобой только через дверь.

Зачем это, спросишь? А затем, сука, чтобы не накосячить! Это называется инкапсуляция. Ты прячешь всю свою внутреннюю кухню: поля-переменные и служебные методы. Пусть снаружи думают, что у тебя там магия, а на самом деле ты просто balance в double хранишь. Главное — если ты завтра передумаешь и вместо double начнёшь хранить баланс в копейках (int), то тебе не придётся бегать по всему коду и всё переписывать. Ты поменяешь логику внутри своих public-методов, а внешний код даже не заметит, потому что он к твоим private-полям и так не имел доступа! Удивление пиздец, да? Вот и я о том же.

Смотри пример, сейчас всё станет ясно:

#include <iostream>
#include <string>

class BankAccount {
private:
    // Вот это наше святое святых. Сюда лезть нельзя.
    std::string accountNumber; // Номер счёта
    double balance;            // Баланс, самый сок
    bool isActive;             // Активен ли счёт

    // А это наш внутренний служебный чертила. Он пишет логи.
    void logTransaction(const std::string& type, double amount) {
        std::cout << "[" << accountNumber << "] " << type << ": " << amount << 'n';
    }

public:
    // А вот это — фасад, лицо нашего класса. Добро пожаловать.
    BankAccount(const std::string& accNum, double initialDeposit)
        : accountNumber(accNum), balance(initialDeposit), isActive(true) {}

    // Положить деньги. Внутри может быть сложная логика, но снаружи — просто метод.
    void deposit(double amount) {
        if (amount > 0 && isActive) {
            balance += amount;
            logTransaction("DEPOSIT", amount); // А вот и наш private-метод работает
        }
    }

    // Снять деньги. Проверяем, хватает ли, активен ли счёт.
    bool withdraw(double amount) {
        if (amount > 0 && isActive && balance >= amount) {
            balance -= amount;
            logTransaction("WITHDRAW", amount);
            return true;
        }
        return false;
    }

    // Геттер. Единственный законный способ узнать баланс снаружи.
    double getBalance() const {
        return balance;
    }

    void deactivate() {
        isActive = false;
        std::cout << "Account " << accountNumber << " deactivated.n";
    }
};

int main() {
    BankAccount myAccount("ACC123", 1000.0);

    myAccount.deposit(500.0); // Окей, публичный метод
    myAccount.withdraw(200.0); // Тоже окей
    std::cout << "Current balance: " << myAccount.getBalance() << 'n'; // Спрашиваем через геттер

    // А теперь попробуем наглость:
    // myAccount.balance = 1000000; // ОШИБКА КОМПИЛЯЦИИ! private-поле, иди нахуй.
    // myAccount.logTransaction("HACK", 9999); // Тоже ОШИБКА! private-метод, не для твоих глаз.

    return 0;
}

Ещё пара важных фишек, чтобы не облажаться:

  • class vs struct: Вот тут прикол. В обычном class всё по умолчанию — private. Написал поле — оно уже приватное. А в struct всё наоборот — по умолчанию public. Так исторически сложилось, ядрёна вошь. Запомни и не путай.
  • Наследование private: Бывает и такое, class Derived : private Base. Это, блядь, жёстко. Это значит, что ВСЁ из родительского класса (Base), даже если там было public, в наследнике (Derived) становится private. Как будто ты взял чужой код и спрятал его в самый дальний чулан. Используется редко, обычно когда нужно не сказать "я — это он", а "я сделан на его основе".
  • friend: А это, чувак, твой кореш, которого ты можешь пустить в свою спальню. Объявил функцию или другой класс friend — и всё, у него есть доступ ко всем твоим private-полям. Сильная власть, поэтому используй её с умом, а то будет пиздопроебибна. Доверия ебать ноль к таким штукам, можно наломать дров.