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

Какие знаешь парадигмы С++?

2.2 Middle🔥 161 комментариев
#ООП и проектирование#Язык C++

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

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

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

Парадигмы программирования в C++

C++ — это мультипарадигменный язык, который поддерживает несколько стилей программирования одновременно. Вот основные парадигмы:

1. Процедурное/Императивное программирование

Получено из языка C. Основано на выполнении последовательности команд и инструкций:

#include <iostream>
#include <vector>

int main() {
    std::vector<int> numbers = {5, 2, 8, 1, 9};
    
    // Процедурный стиль: последовательные инструкции
    int sum = 0;
    for (int i = 0; i < numbers.size(); i++) {
        sum += numbers[i];
    }
    
    int average = sum / numbers.size();
    
    std::cout << "Сумма: " << sum << std::endl;
    std::cout << "Среднее: " << average << std::endl;
    
    return 0;
}

Характеристики:

  • Фокус на как (как выполнить задачу)
  • Изменяемое состояние (переменные)
  • Побочные эффекты
  • Простой контроль потока (циклы, условия)

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

Организует код вокруг объектов, которые содержат данные и методы:

#include <iostream>
#include <string>

class Car {
private:
    std::string make;
    std::string model;
    int year;
    int speed;
    
public:
    Car(const std::string& m, const std::string& md, int y) 
        : make(m), model(md), year(y), speed(0) {}
    
    // Методы
    void accelerate(int increment) {
        speed += increment;
    }
    
    void brake(int decrement) {
        speed -= decrement;
        if (speed < 0) speed = 0;
    }
    
    void display() const {
        std::cout << year << " " << make << " " << model 
                  << " - Скорость: " << speed << " км/ч" << std::endl;
    }
};

int main() {
    Car myCar("Toyota", "Camry", 2023);
    
    myCar.accelerate(50);
    myCar.display();  // 2023 Toyota Camry - Скорость: 50 км/ч
    
    myCar.brake(20);
    myCar.display();  // 2023 Toyota Camry - Скорость: 30 км/ч
    
    return 0;
}

Основные принципы OOP:

  • Инкапсуляция: скрытие внутренней реализации
  • Наследование: создание иерархии классов
  • Полиморфизм: один интерфейс, различные реализации
// Наследование
class Vehicle {  // Базовый класс
public:
    virtual void drive() {
        std::cout << "Транспортное средство едет" << std::endl;
    }
    virtual ~Vehicle() = default;
};

class Car : public Vehicle {  // Наследование
public:
    void drive() override {  // Переопределение
        std::cout << "Машина едет по дороге" << std::endl;
    }
};

class Boat : public Vehicle {
public:
    void drive() override {
        std::cout << "Лодка плывёт по воде" << std::endl;
    }
};

int main() {
    Car car;
    Boat boat;
    
    Vehicle& v1 = car;   // Полиморфизм
    Vehicle& v2 = boat;
    
    v1.drive();  // "Машина едет по дороге"
    v2.drive();  // "Лодка плывёт по воде"
    
    return 0;
}

3. Функциональное программирование

Третирует вычисления как вычисления математических функций, избегая изменения состояния:

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

int main() {
    std::vector<int> numbers = {1, 2, 3, 4, 5};
    
    // Функциональный стиль: чистые функции и трансформации
    auto doubled = numbers;
    std::transform(doubled.begin(), doubled.end(), doubled.begin(),
                   [](int x) { return x * 2; });  // Lambda - анонимная функция
    
    // filter операция
    std::vector<int> evens;
    std::copy_if(numbers.begin(), numbers.end(),
                 std::back_inserter(evens),
                 [](int x) { return x % 2 == 0; });
    
    // reduce операция
    int sum = 0;
    std::for_each(numbers.begin(), numbers.end(),
                  [&sum](int x) { sum += x; });
    
    std::cout << "Сумма: " << sum << std::endl;  // 15
    
    return 0;
}

Характеристики функционального подхода:

  • Чистые функции: одинаковый вывод для одинакового входа
  • Неизменяемость: данные не меняются
  • Функции первого класса: передача функций как аргументы
  • Lambda выражения (C++11+)
  • Higher-order функции: функции, работающие с другими функциями

4. Генерическое программирование (Templates)

Позволяет писать код, работающий с типами, определяемыми при компиляции:

#include <iostream>
#include <vector>
#include <string>

// Шаблон функции
template <typename T>
T maximum(T a, T b) {
    return (a > b) ? a : b;
}

// Шаблон класса
template <typename T>
class Stack {
private:
    std::vector<T> items;
    
public:
    void push(const T& item) {
        items.push_back(item);
    }
    
    T pop() {
        T item = items.back();
        items.pop_back();
        return item;
    }
    
    bool isEmpty() const {
        return items.empty();
    }
};

int main() {
    // Работает с int
    std::cout << maximum(10, 20) << std::endl;  // 20
    
    // Работает со строками
    std::cout << maximum(std::string("apple"), std::string("zebra")) << std::endl;  // zebra
    
    // Stack с int
    Stack<int> intStack;
    intStack.push(1);
    intStack.push(2);
    std::cout << intStack.pop() << std::endl;  // 2
    
    // Stack со строками (тот же код, но другой тип)
    Stack<std::string> stringStack;
    stringStack.push("hello");
    stringStack.push("world");
    std::cout << stringStack.pop() << std::endl;  // world
    
    return 0;
}

Применение генериков:

  • STL контейнеры: std::vector<T>, std::map<K, V>
  • STL алгоритмы: std::sort, std::find
  • Типобезопасность: проверка типов на этапе компиляции

5. Метапрограммирование

Программа, которая манипулирует другими программами или сама собой во время компиляции:

#include <iostream>
#include <type_traits>

// Compile-time вычисления (constexpr)
constexpr int factorial(int n) {
    return (n <= 1) ? 1 : n * factorial(n - 1);
}

// Template метапрограммирование
template <int N>
struct Fibonacci {
    static constexpr int value = Fibonacci<N-1>::value + Fibonacci<N-2>::value;
};

template <>
struct Fibonacci<0> {
    static constexpr int value = 0;
};

template <>
struct Fibonacci<1> {
    static constexpr int value = 1;
};

// Type traits для инспекции типов
template <typename T>
void printInfo(T value) {
    if (std::is_integral_v<T>) {
        std::cout << "Целое число" << std::endl;
    } else if (std::is_floating_point_v<T>) {
        std::cout << "Число с плавающей точкой" << std::endl;
    }
}

int main() {
    // Вычисляется во время компиляции
    std::cout << "5! = " << factorial(5) << std::endl;  // 120
    
    // Также во время компиляции
    std::cout << "Fibonacci(10) = " << Fibonacci<10>::value << std::endl;  // 55
    
    printInfo(42);      // "Целое число"
    printInfo(3.14);    // "Число с плавающей точкой"
    
    return 0;
}

Сравнение парадигм

ПарадигмаФокусКогда использоватьПреимущества
ПроцедурноеКак выполнитьПростые скрипты, алгоритмыПонятность, управление памятью
OOPОбъекты и их взаимодействиеСложные системы, иерархииМодульность, переиспользование кода
ФункциональноеЧистые функцииОбработка данных, параллелизмПредсказуемость, тестируемость
ГенерическоеТипобезопасные шаблоныПереиспользуемые компонентыПроизводительность, безопасность типов
МетапрограммированиеCompile-time вычисленияОптимизация, type safetyПроизводительность, гибкость

Практический пример: Комбинирование парадигм

#include <iostream>
#include <vector>
#include <algorithm>
#include <string>

// OOP
class Person {
private:
    std::string name;
    int age;
    
public:
    Person(const std::string& n, int a) : name(n), age(a) {}
    
    int getAge() const { return age; }
    const std::string& getName() const { return name; }
};

int main() {
    // Генерическое программирование
    std::vector<Person> people = {
        Person("Alice", 30),
        Person("Bob", 25),
        Person("Charlie", 35)
    };
    
    // Функциональное программирование с lambda
    std::vector<Person> adults;
    std::copy_if(people.begin(), people.end(),
                 std::back_inserter(adults),
                 [](const Person& p) { return p.getAge() >= 30; });
    
    // Процедурное программирование
    for (const auto& person : adults) {
        std::cout << person.getName() << ": " << person.getAge() << std::endl;
    }
    // Alice: 30
    // Charlie: 35
    
    return 0;
}

Ключевые моменты

  • C++ поддерживает множество парадигм — выбирайте подходящие для задачи
  • Процедурное — для простых алгоритмов и производительности
  • OOP — для сложных систем с иерархиями
  • Функциональное — для обработки данных и параллелизма
  • Генерическое — для типобезопасных шаблонов
  • Метапрограммирование — для compile-time оптимизаций
  • Лучшая практика — комбинировать парадигмы в одном проекте
Какие знаешь парадигмы С++? | PrepBro