我有一个类似下面的课程:
class Foo {
private:
std::map<std::string, Bar*> bars_by_name;
std::map<std::string, Baz*> bazs_by_name;
};
现在我想允许用户访问两个集合,但隐藏我将对象存储到std :: maps中的实现细节。相反,我希望有成员函数返回,例如由于Bar和Baz属于同一个类层次结构,因此集合的const迭代器甚至可能是从两个集合返回对象的自定义迭代器。考虑到样式,在C ++中执行此操作的正确方法是什么?在Java中,我可能将方法的返回类型设置为Iterable或将集合包装为unmodifiableCollection。
答案 0 :(得分:1)
创建一个隐藏详细信息的界面:
class Foo {
public:
void AddBar(std::string name, Bar*);
void RemoveBar(std::string name);
Bar* GetBar(std::string name);
Bar* GetBar(std::string name) const;
void AddBaz(std::string name, Baz*);
void RemoveBaz(std::string name);
Baz* GetBaz(std::string name);
Baz* GetBaz(std::string name) const;
private:
std::map<std::string, Bar*> bars_by_name;
std::map<std::string, Baz*> bazs_by_name;
};
对于所有用户都知道,你可以将它们存储在列表内的std ::对中,在向量内,或甚至使用并行数组......真的。
编辑:
事实上,您将其存储在地图中,但希望用户迭代底层容器,这些气味会导致设计错误/不正确。要么只允许他们单独访问,要么创建为他们执行此操作的方法。
答案 1 :(得分:1)
您可以将集合的迭代器作为您自己的传递。
class Foo {
private:
typedef std::map<std::string, Bar*> BarContainer;
typedef std::map<std::string, Baz*> BazContainer;
public:
typedef BarContainer::const_iterator ConstBarIterator;
ConstBarIterator beginBars() { return bars_by_name.cbegin(); }
ConstBarIterator endBars() { return bars_by_name.cend(); }
typedef BazContainer::const_iterator ConstBazIterator;
ConstBazIterator beginBazs() { return bazs_by_name.cbegin(); }
ConstBazIterator endBazs() { return bazs_by_name.cend(); }
private:
BarContainer bars_by_name;
BazContainer bazs_by_name;
};
这可以节省您实现自己的迭代器的工作,但是您可以灵活地在以后更改容器类型,并且只需要调用者重新编译。
它没有解决将它们一起迭代的问题。