闲谈C++算法封装:穷举法(二)

2014-11-24 13:20:04 · 作者: · 浏览: 34

  至此,WalkThrough的定义如下:

  template

  class WalkThrough

  public:

  void setState(const State& s) curState = s;

  State getState() const return curState;

  bool getNextFilter();

  bool isOver() const return overFlag;

  private:

  State curState;

  bool overFlag;

  ;

  我们把构造函数与析构函数置后,先考虑起关键作用的getNextFilter()的实现。首先,getNextFileter()由当前的状态跳转为下一状态,然后判断新状态是否为可行,若可行,则停止跳转并返回true,否则继续跳转,重复上述步骤。另一方面,如果已经完成了遍历而还没有找到可行状态,则将overFlag设为false并且返回false.

  我们将跳转操作、判断是否为可行状态操作下放给用户实现:用户相应提供两个函数,然后向WalkThrough对象传入函数指针,供getNextFileter()调用。那么这两个函数应该采用什么样的接口形式比较合适呢?先看看跳转函数,一个很直观的实现是传入一个State对象(或其const引用),然后返回“下一个”State对象,不过至少在返回的时候,值传递会产生State对象的复制操作(诸如NRV优化之类的语言标准外的特定编译器实现不在讨论之列),当State对象比较大的时候,开销是不值得的。我们应当考虑传入State对象的引用,然后“全权委托”跳转函数进行直接修改――把它“变”成下一个状态。可能会有人质疑这样做是否违反了封装原则,但即使摒弃效率方面的权衡,这样做也是合情合理的。跳转函数――不妨视为负责“状态转化”函数,就像一个炼丹炉――有权利、甚至有义务这样做,它的职责是“转化状态”而非“获得状态”。唔……我都觉得自己在语言上过于细究了。嗯,除了转化状态,跳转函数在发现遍历完成之后也应当及时告知调用它的getNextFilter(),否则下放了大部分权力的getNextFilter()是无从知晓的。于是我们的跳转函数接口为:接受一个State的引用,返回一个bool值。如果遍历没有完成,那么函数执行完毕之后State引用将变为它的后继状态,且函数返回true;否则State不变,函数返回false.

  判断是否为可行状态的函数接口则很好定义了:它接受一个constState型引用作为待判断的状态,返回bool值,其中true表示该状态为可行状态,false表示该状态不是可行状态。

  我们将跳转函数以及判断函数的函数指针类型分别定义为StateJumper及Matcher,由于用户可能也会用到这些函数指针类型,我们将定义加到public域中:

  public:

  typedef bool (*StateJumper)(State&);

  typedef bool (*M