Ты не будешь наследовать от std :: vector - PullRequest
177 голосов
/ 04 декабря 2010

Хорошо, это действительно трудно признаться, но у меня сейчас есть сильное искушение унаследовать от std::vector.

Мне нужно около 10 пользовательских алгоритмов для вектора, и я хочу, чтобы они были непосредственно членами вектора. Но, естественно, я хочу иметь и остальную часть интерфейса std::vector. Ну, моя первая идея, как законопослушного гражданина, состояла в том, чтобы иметь std::vector члена в MyVector классе. Но тогда я должен был бы вручную повторно предоставить весь интерфейс std :: vector. Слишком много, чтобы напечатать. Затем я подумал о частном наследовании, так что вместо повторного предоставления методов я бы написал группу using std::vector::member в открытом разделе. Это слишком утомительно на самом деле.

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

Мое решение абсолютно неоправданно? Если так, то почему? Можете ли вы предоставить альтернативу, которая будет иметь дополнительные члены на самом деле члены, но не будет включать в себя перепечатывание всего интерфейса вектора? Я сомневаюсь в этом, но если вы можете, я просто буду счастлив.

Кроме того, кроме того, что какой-то идиот может написать что-то вроде

std::vector<int>* p  = new MyVector

Есть ли какие-либо другие реалистичные опасности в использовании MyVector? Говоря реалистично, я отказываюсь от таких вещей, как представить себе функцию, которая принимает указатель на вектор ...

Ну, я изложил свой случай. Я согрешил. Теперь ты должен простить меня или нет:)

Ответы [ 12 ]

2 голосов
/ 06 декабря 2010

Да, это безопасно, если вы будете осторожны, чтобы не делать то, что небезопасно ... Я не думаю, что когда-либо видел, чтобы кто-то использовал вектор с новым, поэтому на практике вы, вероятно, будете в порядке. Тем не менее, это не распространенная идиома в C ++ ....

Можете ли вы дать больше информации о алгоритмах?

Иногда вы заканчиваете тем, что идете по одной дороге с дизайном, а затем не видите другие пути, по которым вы, возможно, пошли - тот факт, что вы заявляете, что вам нужно вектор с 10 новыми алгоритмами, вызывает у меня тревогу - действительно ли это так? 10 алгоритмов общего назначения, которые может реализовать вектор, или вы пытаетесь создать объект, который является одновременно вектором общего назначения И который содержит специфические для приложения функции?

Я, конечно, не говорю, что вы не должны этого делать, просто из-за информации, которую вы дали, звучат сигналы тревоги, что заставляет меня думать, что, возможно, что-то не так с вашими абстракциями, и есть лучший способ достичь того, что вы хотите.

0 голосов
/ 18 мая 2018

Здесь, позвольте мне представить еще 2 способа сделать то, что вы хотите.Один - это другой способ переноса std::vector, другой - способ наследования, не дающий пользователям возможности что-либо сломать:

  1. Позвольте мне добавить еще один способ переноса std::vector без написания большого количества функций.фантики.

#include <utility> // For std:: forward
struct Derived: protected std::vector<T> {
    // Anything...
    using underlying_t = std::vector<T>;

    auto* get_underlying() noexcept
    {
        return static_cast<underlying_t*>(this);
    }
    auto* get_underlying() const noexcept
    {
        return static_cast<underlying_t*>(this);
    }

    template <class Ret, class ...Args>
    auto apply_to_underlying_class(Ret (*underlying_t::member_f)(Args...), Args &&...args)
    {
        return (get_underlying()->*member_f)(std::forward<Args>(args)...);
    }
};
Наследование от std :: span вместо std::vector и избежание проблемы с dtor.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...