【问题标题】:Allowing access to container objects in C++允许访问 C++ 中的容器对象
【发布时间】:2012-06-19 22:37:12
【问题描述】:

我有一个像下面这样的课程:

class Foo {
private:
    std::map<std::string, Bar*> bars_by_name;
    std::map<std::string, Baz*> bazs_by_name;
};

现在我想允许用户访问这两个集合,但隐藏我将对象存储到 std::maps 的实现细节。相反,我希望有返回的成员函数,例如集合的 const 迭代器,甚至可能是从两个集合返回对象的自定义迭代器,因为 Bar 和 Baz 属于同一个类层次结构。考虑到风格,在 C++ 中执行此操作的正确方法是什么?在 Java 中,我可能会将方法的返回类型设置为 Iterable 或将集合包装到不可修改的Collection 中。

【问题讨论】:

  • 如果你使用any_iterator 之类的东西,你可以隐藏底层类型而不会泄露细节。您也可以使用 Boost 的 transform_iterator 或 zip_iterator 作为中介,而不需要更明智的使用。

标签: c++


【解决方案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;
};

这为您节省了实现自己的迭代器的工作,但让您可以灵活地在以后更改容器类型并且只需要调用者重新编译。

它不能解决同时迭代它们的问题。

【讨论】:

  • 谢谢。我用 Boost 的迭代器尝试了一些东西,但不能让它们工作,所以我决定先做点别的。我也发现了这个库,但它似乎已经是 10 多年前的 alpha 版本了:zib.de/weiser/vtl
【解决方案2】:

创建隐藏细节的界面:

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::pair 中的列表内、向量内,甚至使用并行数组...任何东西。

编辑:

您将其存储在地图中但希望 用户 遍历底层容器的事实是设计不佳/不正确。要么只允许他们如上所述单独访问,要么创建为他们执行此操作的方法。

【讨论】:

  • 除了 Oli 指出的以外,暴露迭代器不必暴露底层类型。迭代器可以是抽象的,例如,像上面指出的 any_iterator。
猜你喜欢
  • 2013-09-10
  • 2011-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多