Лучший способ вставить элементы из конструктора производного класса в приватный std :: vector базового класса? - PullRequest
3 голосов
/ 07 апреля 2010

У меня есть эти классы:

class Base
{
...
private:
std::vector<X> v;
};

class Derived : public Base
{
Derived(X*, int n);
};

где конструктору Derived передается массив элементов Xs, которые мне нужно вставить в мой вектор v в базовом классе. (X - умный указатель)

В настоящее время я вижу два способа сделать это:

  1. Создать функцию в базе: InsertItem (X *), который вставит элемент в вектор (1 на 1)
  2. Создать вектор в Derived, который содержит полный список, а затем получить его в базу по перемещение всего вектора.

Я не вижу никаких преимуществ для # 2, но мне было интересно, если # 1 было хорошим решением или есть ли лучшие способы сделать это.

Спасибо!

Ответы [ 5 ]

5 голосов
/ 07 апреля 2010

Существует третий вариант, если вы можете изменить Base.Вы можете создать вектор protected, который обеспечит полный доступ базовым классам:

class Base
{
...
protected:
    std::vector<X> v;
};

Ваш базовый класс теперь может напрямую работать с v.Если вам нужно предоставить большую часть векторной функциональности для Derived, это самый простой способ.

Если нет, я бы просто добавил одну функцию (то есть вариант # 1) и сделал бы ее защищенной:

class Base
{
...

protected:
    void push_back(const X &x)
    {
        v.push_back(x);
    }

private:
    std::vector<X> v;
};
4 голосов
/ 07 апреля 2010

Другой вариант - создать в базе (открытый или защищенный) конструктор, который будет принимать параметры и напрямую заполнять вектор. Не нужно создавать или передавать промежуточные векторы.

class Base
{
 . . .
protected:
    Base(X* x,int n);
 . . .
};

class Derived : public Base
{
    Derived(X* xes, int n):Base(xes,n){};
};
1 голос
/ 07 апреля 2010

Если вы хотите, чтобы контейнер в базовом классе оставался закрытым, вы можете рассмотреть возможность добавления общедоступной (или защищенной) функции в Base, чтобы позволить производному классу добавить диапазон.Таким образом, контейнер типа Base может быть инкапсулирован (Derived не должен знать, что это vector), и Derived все равно может передать все это за один выстрел:

class Base
{
...
private:
    std::vector<X> v;

protected
    template <class iterator_t>
    void assign( iterator_t first, iterator_t last) {
        v.assign( first, last);
    }
};

class Derived : public Base
{
Derived(X* p, int n) {
    Base::assign( p, p+n);
}
};

Это не слишком инкапсуляция, но контейнер можно изменить, изменив производный класс, и можно легко написать производный класс, который при желании принимает данные в форме, отличной от массива.И , как предложил zdan , эта функциональность может быть частью открытого или защищенного конструктора для Base, если это имеет больше смысла (что вероятно).

Идея использования диапазонов итераторов для представлениясодержимое или подмножество контейнера широко распространено в STL.

1 голос
/ 07 апреля 2010

Если вы можете, я бы создал конструктор protected в Base, который принимает аргумент X* точно так же, как конструктор Derived, а затем в списке инициализации конструктора Derived передал аргумент Защищенный конструктор Base и его фактическая вставка.

0 голосов
/ 07 апреля 2010

Вы должны установить переменную-член равной protected, чтобы классы, которые наследуют Base, могли получить к ней доступ. В качестве альтернативы можно оставить приватную переменную-член, но добавить метод доступа protected, чтобы позволить классам, которые наследуют base, добавить в вектор и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...