我有一个类,其中包含一个std :: list。我想公开这个列表,但只是以这样的方式,它包含的结构和数据是只读的,但仍然可以与迭代器一起使用。
我得到'工作'atm的方式是返回列表的副本。这使我的班级“安全”,但当然没有阻止调用者修改他们的列表副本而没有获得正确的数据。
有更好的方法吗?
答案 0 :(得分:15)
为什么不返回const std::list&
?
答案 1 :(得分:9)
不要暴露列表本身(根本不暴露),只需将const_iterator
暴露给它的开头和结尾。请参阅cbegin()
和cend()
以获取相关帮助...
答案 2 :(得分:4)
返回一个const引用:
const std::list<T>& getList() const;
或只返回const迭代器:
std::list<T>::const_iterator getListBegin() const;
std::list<T>::const_iterator getListEnd() const;
答案 3 :(得分:4)
将一个人的数据成员暴露给外界存在依赖性问题。
如果您决定更改属性以获得更好的结果(因为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;
};
您只需将所有操作转发给实际的迭代器,而您的客户端(如果更改容器则必须重新编译)不会意外使用非混淆类型。
然后,第三个解决方案与第一个解决方案类似,不同之处在于你抽象类型......虽然(对于列表)效率很低,所以我不会真正建议它:迭代器应该是便宜的复制,你不想new
任何东西。
答案 4 :(得分:3)
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_;
};