代码之家  ›  专栏  ›  技术社区  ›  Igor

德米特定律或返回整个向量

  •  4
  • Igor  · 技术社区  · 15 年前

    哪一个更好:

    public:
      const vector<int> & GetPointsVector();
    private:
      vector<int> PointsVector;
    

    或:

    public:
      int GetCurrentPoint();
      void MoveToFirstPoint();
      void MoveToNextPoint();
      bool IsAtLastPoint();
      size_t GetNumberOfPoints();
    private:
      vector<int> PointsVector;
    
    5 回复  |  直到 15 年前
        1
  •  13
  •   amit kumar    15 年前

    两者都不是。最好返回begin()和end()迭代器,或者更好地返回迭代器的boost::range。

    private:
            typedef std::vector<int>            PointsContainer;
    public: 
            typedef boost::iterator_range<PointsContainer::const_iterator> PointsRange;
            PointsRange getPointsRange() const {
                return boost::make_iterator_range(pointsContainer_.begin(), pointsContainer_.end()); 
            }
    

    优点是遍历逻辑隐藏在范围/迭代器中

    int p;
    foreach(p, obj.getPointsRange()) {
       //...
    }
    

    否则

    C::PointsRange r = obj.getPointsRange();
    for(C::PointsRange::iterator i = r.begin(); i != r.end(); ++i) {
          int p = *i;
          //...
    }
    
        2
  •  2
  •   fizzer    15 年前

    也不将需要此类内部知识的函数转换为成员函数。

        3
  •  2
  •   David Hanak    15 年前

        4
  •  2
  •   dirkgently    15 年前

    没有正确的答案。答案会随着环境的变化而变化,而目前我们所知甚少。

    这取决于你们班的客户。在大多数情况下,您不希望临时检查器更改对象的状态,因此在一定程度上最好返回对对象的引用 const 对象但是,在这种情况下,我还将函数设为

     /* a design const - this accessor does not change the state */
     const vector<int> & GetPointsVector() const;
    

    这也是有效的,因为您没有将重对象作为返回值传递(这是一个不同的问题,现在大多数编译器都使用RVO)。

    typedef vector<int>::iterator _MyItr;
    _MyItr begin() const;
    _MyItr begin();
    
    _MyItr end() const;
    _MyItr end();
    

    这将符合STL的设计方式。但是,在指定客户端可以期望的迭代器类型时要小心(例如:如果类规范说返回的迭代器是 RandomIterators ,它对您的实现设定了一定的期望)。

        5
  •  0
  •   Mykola Golubyev    15 年前

    我更喜欢封装内部数据表示和使用forEachSomething模板公共功能。或者,如果您有boost,您可以避免模板化forEachSomething,并将实现放在.cpp文件中。

    class Class
    {
    public:
        Class()
        {
            points_.push_back( 1 );
            points_.push_back( 5 );
            points_.push_back( 7 );
        }
    
        template <typename TFunction>
        void forEachPoint( TFunction function )
        {
            std::for_each( points_.begin(), points_.end(),
                           function );
        }
    
        void forEachPoint2( boost::function< void (int ) > function )
        {
            std::for_each( points_.begin(), points_.end(),
                           function );
        }
    private:
        std::vector<int> points_;
    };
    
    void print( int a )
    {
        std::cout << a << std::endl;
    }
    
    int main()
    {
        Class object;
        object.forEachPoint( print );
    }