У меня есть класс, который содержит, среди прочего, станд.:: список. Я хочу выставить этот список, но только таким способом, которым структурой и данными он содержит, только для чтения, но все еще может использоваться с итераторами.
Путем у меня есть он, 'рабочий' банкомат должен возвратить копию списка. Этот отпуск мой класс 'безопасный', но конечно не делает ничего, чтобы мешать вызывающей стороне изменить их копию списка и не получить правильные данные.
Существует ли лучший путь?
Почему бы не вернуть const std :: list &
вместо этого?
Вместо того, чтобы открывать сам список (вообще), просто выставьте const_iterator
до его начала и конца. См. cbegin ()
и cend ()
для помощи в этом ...
Верните константную ссылку:
const std::list<T>& getList() const;
или просто верните константные итераторы:
std::list<T>::const_iterator getListBegin() const;
std::list<T>::const_iterator getListEnd() const;
Существует проблема зависимости в предоставлении доступа к члену данных внешнему миру.
Если вы решите изменить свой атрибут на что-то лучшее (потому что 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;
};
Вы просто перенаправляете все операции фактическому итератору, и ваши клиенты (хотя им придется перекомпилировать, если вы меняете контейнер) не могут случайно использовать неализованный тип.
Затем третье решение похоже на первое, за исключением того, что вы абстрагируете тип ... хотя оно довольно неэффективно (для списка), поэтому я бы не советовал его: предполагается, что итераторы дешево копировать, вы не хотите ничего нового
.
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_;
};