我希望我的c ++代码能够封装,因为我可以通过这种方式返回迭代器吗?
const map<string,bool>::iterator getFollowers() {
return followers.begin();
}
const map<string,bool>::iterator getFollowing() {
return following.begin();
}
完整代码:
#ifndef twitClient_twitUser_h
#define twitClient_twitUser_h
#include <map>
#include <iostream>
#include <string>
using namespace std;
class user {
string username;
map<string,bool> followers;
map<string,bool> following;
string name;
public:
user(string username):username(username) {
followers [username] = false;
following [username] = false;
}
bool removeFollower (string friendName);
bool addFollower(string friendName);
bool stopFollowing(string friendName);
bool startFollowing(string friendName);
const map<string,bool>::iterator getFollowers() {
return followers.begin();
}
const map<string,bool>::iterator getFollowing() {
return following.begin();
}
};
答案 0 :(得分:2)
你的方法没有错,除了你可能想要添加const访问方法,例如
map<string,bool>::const_iterator getFollowers() const;
另外,您还希望添加对end()
迭代器的访问权限。
关于封装,您封装了地图,但您的客户端被map<string, bool>::iterator
公开。有一篇关于隐藏这些依赖项here的非常有趣的文章。这绝不是微不足道的,但仍值得考虑。
答案 1 :(得分:1)
是和否。
封装有几个含义。
const_iterator
)所以,你不要让其他人控制你的内部(好),但你仍然会暴露实施细节,如果你改变了followers
或following
的实施方式,你就会破坏客户。
一种可能的解决方案是引入循环结构(例如foreach):
template <typename Pred>
void user::foreachFollower(Pred& p) const {
for (auto const& f: followers) { p(f); }
}
这更灵活,因为如果您将地图从<string, bool>
更改为<string, int>
(而不是计算数字),您可以随时更改功能:
template <typename Pred>
void user::foreachFollower(Pred& p) const {
for (std::pair<std::string, bool> const& f: followers) { p(f); }
}
这样您的客户就不会受损。它们也是精心设计的技巧,用于检测客户端是否可以处理std::pair<std::string, int>
,但它们(有点)难以实现。
另一方面,仅提供begin
迭代器是不够的,它们还需要end
个。
答案 2 :(得分:1)
如果您进一步考虑这个问题,我认为可能存在一些设计问题。似乎您将在此设置中保留许多容器并设置跟随者/后续bool以说明条件是否为真。一分钟后回到这一点。
如果在使用之前/期间使用其他方法操作容器,则传回迭代器可能非常危险。因此,对于您的问题,我会考虑传递对要分析/操作的容器的引用,如果使用多线程(在这些多核心日期我们需要始终考虑这一点)使用互斥锁来使容器线程安全或{{ 3}}类型设计和简单的安全队列实现。
对于此设置,如果您有一组封闭的用户,或者如果您有多对多的情况,那么可能最好考虑矩阵类型设计,然后可能会考虑类似active object的内容。这可以提供更清晰,更可扩展的设计。