1

我希望我的 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();

    }


};
4

3 回答 3

2

您的方法没有任何问题,只是您可能还想添加 const 访问方法,例如

map<string,bool>::const_iterator getFollowers() const;

另外,您还想添加对end()迭代器的访问。

关于封装,您封装了地图,但您的客户暴露于map<string, bool>::iterator. 有一篇关于在此处隐藏这些依赖项的非常有趣的文章。这绝不是微不足道的,但仍然值得考虑。

于 2012-06-16T17:02:23.257 回答
1

是和不是。

封装有多种含义。

  • 以较轻的形式,这意味着该类可以完全控制封装的成员,这可能是这里的情况(如果您返回 a const_iterator
  • 在其较重的形式中,这意味着类实现细节不会泄漏到外部单词中,这里不是这种情况

因此,您不要让其他人控制您的内部(很好),但您仍然会公开实现细节,如果您更改了如何followersfollowing在幕后实现,则会破坏客户端。

一种可能的解决方案是引入循环构造(例如 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一个。

于 2012-06-16T17:09:17.667 回答
1

如果您进一步考虑这个问题,我认为可能存在一些设计问题。似乎您将在此设置中保留许多容器并设置跟随者/跟随布尔值来说明条件是否为真。一分钟后回到这个。

如果在使用之前/期间从另一个方法操作容器,则传回迭代器可能非常危险。因此,对于您的问题,我会考虑传递对要分析/操作的容器的引用,如果使用多线程(在这些多核时代,我们需要始终考虑这一点)使用互斥锁使容器线程安全或活动对象类型设计和简单的安全队列实现。

对于这种设置,如果您有一个封闭的用户组,或者如果您有多对多的情况,那么考虑使用矩阵类型设计可能会更好,那么也许考虑像boost multi index之类的东西。这可以提供更清晰更可扩展的设计。

于 2012-06-16T17:14:01.703 回答