如何将'this'作为参数传递给另一个没有循环依赖关系的类构造函数?

How do you pass 'this' as an argument to another class constructor without circular dependencies?

本文关键字:依赖 循环 关系 构造函数 this 参数传递 另一个      更新时间:2023-10-16

我特别想到了策略模式(设计模式,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 的文件中进行实例化? 这里的最佳实践是什么?

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

  1. 前向申报Analysisanalysis.hstrategies.h
  2. 定义StrategyBase和子类(不要使用Analysis的内联方法)(strategies.h
  3. 定义Analysis(可能已经使用使用策略的内联方法)(analysis.h
  4. 实现Analysis和策略类的非内联方法 ( analysis.cpp

analysis.cpp还需要包含strategy.h来获取策略的完整定义。由于它是源文件,因此没有循环依赖项。

如果要传递指针(或引用),则无需实例化类: 使用前向声明。

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