5

我正在特别考虑策略模式(设计模式,GoF94),其中建议传递给策略构造函数的上下文可以是包含策略(作为成员)本身的对象。但以下方法不起作用:

//analysis.h

class StrategyBase;
class Strategy1;
class Strategy2;
class Analysis
{
   ...
      void ChooseStrategy();
   private:
      StrategyBase* _s;
      ...
};

//analysis.cpp

void Analysis::ChooseStrategy()
{
   if (...) _s = new Strategy1(this);
   else if (...) _s = new Strategy2(this);
   ...
}

//strategy.h

#include analysis.h
...

然后 StrategyBase 及其子类访问 Analysis 的数据成员。

这是行不通的,因为您无法在定义之前实例化 Strategy* 类。但它的定义取决于分析的定义。那么你应该怎么做呢?将选择策略替换为

void SetStrategy(StrategyBase* s) { _s = s; }

并在#include analysis.h和strategy.h的文件中进行实例化?这里的最佳做法是什么?

4

4 回答 4

6

除了非常一般的状态/策略之外,您将始终在状态/策略模式中具有循环依赖关系。但是您可以限制相应其他类的大小(Lakos)使用,使其至少可以编译:

  1. 前向声明Analysisanalysis.hstrategies.h
  2. 定义StrategyBase和子类(不要内联使用的方法Analysis)(strategies.h
  3. 定义Analysis(可能已经使用了使用策略的内联方法)(analysis.h
  4. 实现Analysis和策略类的非内联方法 ( analysis.cpp)
于 2011-05-09T17:13:47.523 回答
3

analysis.cpp还需要包含strategy.h获取策略的完整定义。因为它是一个源文件,所以没有循环依赖。

于 2011-05-09T17:07:01.773 回答
1

如果要传递指针(或引用),则不需要实例化类:使用Forward Declaration

于 2011-05-09T17:05:17.897 回答
0

c++ 的一个重要特性有时很难弄清楚,即需要以正确的顺序为编译器提供类。类之间的依赖关系决定了需要使用哪个顺序。人们希望将每个类放在单独的.h文件中并不容易,因此在决定#include的顺序时需要多次提供类的顺序。虽然人们正在学习头文件和类的依赖关系,但建议将每个类放在同一个 .h 文件中,因为这将迫使您只决定一次顺序。在学习了正确的顺序之后,您可以再次开始使用将所有类放在单独的头文件中的良好约定。

于 2011-05-09T17:33:12.427 回答