Недостатки наследования от std::vector

MyVector синтаксически допустим, но vector не предоставляет безопасный полиморфный интерфейс расширения. Отсутствие виртуального деструктора делает удаление такого объекта через vector* некорректным.

Короткий ответ

Что ответить на собеседовании

MyVector синтаксически допустим, но vector не предоставляет безопасный полиморфный интерфейс расширения. Отсутствие виртуального деструктора делает удаление такого объекта через vector* некорректным.

Подробный разбор

Ответ с пояснениями

Условие

Объясните, почему наследовать от std::vector считается плохой практикой, хотя технически это возможно.

// Перемещающий оператор присваивания
_CONSTEXPR20_CONTAINER vector& operator=(vector&& _Right) noexcept(
    _Move_assign<_Right, _Choose_pocma<_Alty>>()) {
    if (this != _STD addressof(_Right)) {
        _Move_assign(_Right, _Choose_pocma<_Alty>{});
    }
    return *this;
}

// Деструктор
_CONSTEXPR20_CONTAINER ~vector() noexcept {
    _Tidy();
# if _ITERATOR_DEBUG_LEVEL != 0
    auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alty, _Getal());
    _Delete_plain_internal(_Alproxy, _STD exchange(_Mypair._Myval2._Myproxy, nullptr));
# endif
}
// Приватный метод добавления элемента
template <class... _Valty>
_CONSTEXPR20_CONTAINER decltype(auto)
_Emplace_back_with_unused_capacity(_Valty&&... _Val) {
    auto& _My_data = _Mypair._Myval2;
    pointer& _Mylast = _My_data._Mylast;
    _STL_INTERNAL_CHECK(_Mylast != _My_data._Myend); // проверка свободного места

    _Alty_traits::construct(_Getal(), _Unfancy(_Mylast), _STD forward<_Valty>(_Val)...);
    _Orphan_range(_Mylast, _Mylast);
    _Ty& _Result = *_Mylast;
    ++_Mylast;

# if _HAS_CXX17
    return _Result;
# else
    (void)_Result;
# endif
}

Что произойдёт, если объявить такой класс:

class MyVector : public std::vector<int> {
    std::string metadata;
};

Ответ

MyVector синтаксически допустим, но vector не предоставляет безопасный полиморфный интерфейс расширения. Отсутствие виртуального деструктора делает удаление такого объекта через vector* некорректным.

При обычном уничтожении переменной типа MyVector поле metadata будет очищено правильно. Проблема появляется при обращении с объектом как с полиморфной базой либо изменении базовой части в обход правил производного класса.

Методы vector не виртуальные: одноимённый метод наследника не перехватит все способы изменения данных. Копирование в отдельный vector также не переносит metadata. Обычно следует хранить vector внутри своего класса и явно предоставлять нужные операции.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее