← Назад к вопросам

Что такое ключевое слово explicit?

1.3 Junior🔥 111 комментариев
#Язык C++

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Объектно-ориентированное программирование (ООП)

ООП — парадигма программирования, в которой код организуется вокруг объектов, содержащих данные (состояние) и поведение (методы). Это один из наиболее распространённых подходов в современной разработке.

Четыре столпа ООП

1. Инкапсуляция (Encapsulation)

Суть: скрыть внутренние детали реализации, предоставить только публичный интерфейс.

class BankAccount {
private:
    double balance; // Скрыто от внешнего мира
    
    // Приватный метод
    void log_transaction(const std::string& msg);
    
public:
    // Публичный интерфейс
    bool withdraw(double amount) {
        if (amount <= balance) {
            balance -= amount;
            log_transaction("Withdrawal");
            return true;
        }
        return false;
    }
    
    double get_balance() const {
        return balance;
    }
};

int main() {
    BankAccount account;
    // account.balance = -1000; // ОШИБКА - balance приватна!
    account.withdraw(100); // OK - через публичный метод
}

Преимущества:

  • Контроль над состоянием (невозможно установить невалидное)
  • Скрытие деталей реализации (можно менять внутри)
  • Упрощение интерфейса класса

2. Наследование (Inheritance)

Суть: создание иерархии классов, где подкласс наследует свойства и методы родителя.

class Animal {
protected:
    std::string name;
    
public:
    Animal(const std::string& n) : name(n) {}
    virtual void make_sound() { std::cout << "Generic sound"; }
    virtual ~Animal() = default;
};

class Dog : public Animal {
private:
    int breed_id;
    
public:
    Dog(const std::string& name, int breed) 
        : Animal(name), breed_id(breed) {}
    
    void make_sound() override { std::cout << "Woof!"; }
    
    // Новое свойство
    int get_breed() const { return breed_id; }
};

class Cat : public Animal {
public:
    Cat(const std::string& name) : Animal(name) {}
    void make_sound() override { std::cout << "Meow!"; }
};

Типы наследования:

  • public — is-a отношение, полный доступ
  • protected — для промежуточных классов
  • private — has-a отношение, не рекомендуется

3. Полиморфизм (Polymorphism)

Суть: один интерфейс, множество реализаций.

Полиморфизм времени выполнения (runtime):

void describe_animal(Animal* animal) {
    std::cout << "The animal says: ";
    animal->make_sound(); // Вызовет нужный метод
}

int main() {
    Dog dog("Rex", 1);
    Cat cat("Whiskers");
    
    describe_animal(&dog);  // "The animal says: Woof!"
    describe_animal(&cat);  // "The animal says: Meow!"
}

Полиморфизм времени компиляции (compile-time) - шаблоны:

template<typename T>
void print_value(const T& value) {
    std::cout << value; // Компилятор создаст версию для каждого типа
}

// Специализация
template<>
void print_value<std::vector<int>>(const std::vector<int>& v) {
    for (int x : v) std::cout << x << " ";
}

4. Абстракция (Abstraction)

Суть: предоставить упрощённое представление объекта, скрыв сложность.

// Абстрактный интерфейс - пользователь не знает деталей
class DataStore {
public:
    virtual void save(const std::string& data) = 0;
    virtual std::string load() = 0;
    virtual ~DataStore() = default;
};

// Конкретные реализации
class FileStore : public DataStore {
private:
    std::string filename;
public:
    void save(const std::string& data) override {
        // Деталь: работа с файлами
    }
    std::string load() override {
        // Деталь: чтение файлов
    }
};

class DatabaseStore : public DataStore {
private:
    std::string connection_string;
public:
    void save(const std::string& data) override {
        // Деталь: SQL запросы
    }
    std::string load() override {
        // Деталь: SQL запросы
    }
};

// Пользователь работает с абстракцией, не зная реализации
void backup(DataStore* store, const std::string& data) {
    store->save(data); // Не важно - файл или БД
}

Практический пример: система платежей

// Абстрактный платёж
class Payment {
public:
    virtual bool process(double amount) = 0;
    virtual ~Payment() = default;
};

// Конкретные реализации
class CreditCardPayment : public Payment {
private:
    std::string card_number;
    
public:
    CreditCardPayment(const std::string& card) : card_number(card) {}
    
    bool process(double amount) override {
        // Проверка карты, коммуникация с процессором...
        return true;
    }
};

class PayPalPayment : public Payment {
private:
    std::string email;
    
public:
    PayPalPayment(const std::string& email) : email(email) {}
    
    bool process(double amount) override {
        // API вызов к PayPal...
        return true;
    }
};

// Инкапсуляция логики платежа
class Order {
private:
    std::vector<Item> items;
    std::unique_ptr<Payment> payment_method;
    
public:
    void set_payment(std::unique_ptr<Payment> payment) {
        payment_method = std::move(payment);
    }
    
    bool checkout() {
        double total = calculate_total();
        return payment_method->process(total);
    }
    
private:
    double calculate_total() const {
        // Логика расчёта
    }
};

int main() {
    Order order;
    
    // Полиморфизм: можем менять метод платежа
    order.set_payment(std::make_unique<CreditCardPayment>("1234-5678"));
    order.checkout();
    
    // Или
    order.set_payment(std::make_unique<PayPalPayment>("user@example.com"));
    order.checkout();
}

ООП vs процедурное программирование

ООППроцедурное
Данные + методы вместеДанные отдельно от функций
Модели реального мираПоследовательность операций
ПереиспользуемостьКопирование кода
Проще расширятьСложнее модифицировать

SOLID принципы в ООП

  • S - Single Responsibility: один класс - одна ответственность
  • O - Open/Closed: открыт для расширения, закрыт для модификации
  • L - Liskov Substitution: подклассы взаимозаменяемы
  • I - Interface Segregation: много узких интерфейсов лучше, чем один большой
  • D - Dependency Inversion: зависимости от абстракций, не от конкретики

Когда ООП подходит

✓ Больших приложений с сложной логикой ✓ Командной разработки (чёткая структура) ✓ Долгоживущих проектов (проще менять) ✓ Когда есть иерархия сущностей

✗ Простых скриптов (оverkill) ✗ Когда нужна максимальная производительность (overhead) ✗ Функционального программирования (другая парадигма)