我正在考虑策略模式(Design Patterns,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 *类。但它的定义取决于分析的定义。那么你应该怎么做呢?用
替换ChooseStrategyvoid SetStrategy(StrategyBase* s) { _s = s; }
并在#include analysis.h和strategy.h的文件中进行实例化?这里最好的做法是什么?
答案 0 :(得分:6)
除了非常一般状态/策略之外,您将始终在状态/策略模式中具有循环依赖关系。但是你可以限制相应的其他类的in-size (Lakos) use,使其至少编译:
Analysis
(analysis.h
或strategies.h
)StrategyBase
和子类(不要使用Analysis
的内联方法)(strategies.h
)Analysis
(可能已使用使用策略的内联方法)(analysis.h
)Analysis
和策略类的非内联方法(analysis.cpp
)答案 1 :(得分:3)
analysis.cpp
还需要包含strategy.h
来获取策略的完整定义。由于它是源文件,因此没有循环依赖。
答案 2 :(得分:1)
如果您传递指针(或引用),则无需实例化类:使用Forward Declaration。
答案 3 :(得分:0)
有时很难弄清楚c ++的一个重要特性是需要以正确的顺序为编译器提供类。类之间的依赖关系决定了需要使用哪个顺序。它不会让人们想要将每个类放在单独的.h文件中变得更容易,因此在决定#include的顺序时,需要多次提供类的顺序。虽然人们正在学习标题和类依赖关系,但建议将每个类放在同一个.h文件中,因为这会迫使您只决定一次。在学习了正确的顺序之后,您可以再次开始使用将所有类放在单独的头文件中的良好约定。