Как расширить функциональность класса std::vector в C++?

«Как расширить функциональность класса std::vector в C++?» — вопрос из категории STL, который задают на 25% собеседований C/C++ Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Прямое наследование от std::vector не рекомендуется, так как у него нет виртуального деструктора, что может привести к утечкам памяти. В C++ предпочтительны два подхода: композиция и свободные функции (не-члены).

1. Композиция (предпочтительно): Создайте свой класс, который содержит std::vector как приватный член и предоставляет нужный интерфейс.

template<typename T>
class MyVector {
private:
    std::vector<T> data;
public:
    // Делегирование стандартных методов
    void push_back(const T& value) { data.push_back(value); }
    size_t size() const { return data.size(); }
    T& operator[](size_t idx) { return data[idx]; }
    const T& operator[](size_t idx) const { return data[idx]; }

    // Добавление новой функциональности
    void remove_duplicates() {
        std::sort(data.begin(), data.end());
        auto last = std::unique(data.begin(), data.end());
        data.erase(last, data.end());
    }

    // Предоставление доступа к итераторам для работы с алгоритмами STL
    auto begin() { return data.begin(); }
    auto end() { return data.end(); }
};

2. Свободные функции (следуя принципам STL): Многие операции в STL реализованы как шаблонные функции, работающие с итераторами. Это наиболее гибкий и расширяемый способ.

template<typename T>
void custom_algorithm(std::vector<T>& vec) {
    // Работа с вектором через его публичный интерфейс
    if (!vec.empty()) {
        std::transform(vec.begin(), vec.end(), vec.begin(),
                       [](const T& val) { return val * 2; });
    }
}

Наследование от std::vector допустимо только в очень узких случаях, когда вы точно контролируете время жизни объекта и не используете полиморфизм, но это нарушает принципы проектирования STL и чревато ошибками.