得秒的定律或返回整个向量

时间:2009-03-25 08:54:15

标签: c++ oop vector law-of-demeter

哪一个更好:

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 个答案:

答案 0 :(得分:13)

两者都不是。最好返回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;
      //...
}

答案 1 :(得分:2)

都不是。使需要对类内部的这种深入了解的函数成为一个成员函数。

答案 2 :(得分:2)

在我看来,第一个替代方法(严格地使用const关键字)更好,因为那时你可以使用标准接口来访问向量的成员(例如迭代器等)。仅当您没有其他选项来保护数据免遭意外修改时,才需要第二个选项(即专用访问方法)。

答案 3 :(得分:2)

没有正确答案。答案会因环境而异,目前我们的情况很少。

这取决于您班级的客户。在大多数情况下,您不希望临时检查器更改对象的状态,因此最好在某种程度上返回对const对象的引用。但是,在这种情况下,我还要将函数设为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,它会对您的实现设置一定的期望值。)

答案 4 :(得分:0)

我更喜欢封装内部数据表示并使用forEachSomething模板公共功能。或者,如果你有提升,你可以避免模板化的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 );
}