Предоставление std :: list только для чтения - PullRequest
8 голосов
/ 04 июня 2010

У меня есть класс, который содержит, помимо прочего, std :: list. Я хочу раскрыть этот список, но только таким образом, чтобы структура и содержащиеся в нем данные были доступны только для чтения, но все еще могли использоваться с итераторами.

Способ, которым я работаю, - вернуть копию списка. Это делает мой класс «безопасным», но, конечно, ничего не делает для того, чтобы вызывающий абонент не мог изменить свою копию списка и не получить нужные данные.

Есть ли лучший способ?

Ответы [ 5 ]

15 голосов
/ 04 июня 2010

Почему бы не вернуть const std::list& вместо этого?

9 голосов
/ 04 июня 2010

Вместо того, чтобы выставлять сам список (вообще), просто выставьте const_iterator s к его началу и концу. См. cbegin() и cend() для помощи в этом ...

4 голосов
/ 04 июня 2010

Существует проблема зависимости при представлении члена данных внешнему миру.

Если вы решите изменить свой атрибут на что-то лучшее (потому что list является последним средством контейнера), или потому что у вас естьновые требования, тогда все ваши клиенты будут затронуты, и это плохо.

Одна простая альтернатива - предложить typedef:

typedef std::list<Foo>::const_iterator const_iterator;

ЕСЛИ ваши клиенты используют ваш псевдоним,тогда это просто вопрос перекомпиляции кода.

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

class const_iterator
{
public:

private:
  typedef std::list<Foo>::const_iterator base_type;
  base_type mBase;
};

Вы просто пересылаете всеоперации с реальным итератором, и ваши клиенты (хотя им придется перекомпилировать, если вы измените свой контейнер) не могут случайно использовать несвязанный тип.

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

4 голосов
/ 04 июня 2010

Возвращает постоянную ссылку:

const std::list<T>& getList() const;

или просто вернуть константные итераторы:

std::list<T>::const_iterator getListBegin() const;
std::list<T>::const_iterator getListEnd() const;
3 голосов
/ 04 июня 2010
class foo {
  private:
     typedef std::list<bar> bar_cont_t;

  public:
     typedef bar_const_t::const_iterator bar_const_iterator;

     bar_const_iterator bar_begin() const {return bar_data_.begin();}
     bar_const_iterator bar_end  () const {return bar_data_.end  ();}

     // whatever else

  private:
     bar_cont_t bar_data_;
};
...