C++ 你如何通过';这';作为没有循环依赖项的另一个类构造函数的参数?

C++ 你如何通过';这';作为没有循环依赖项的另一个类构造函数的参数?,c++,include,dependencies,strategy-pattern,C++,Include,Dependencies,Strategy Pattern,我特别想到了策略模式(设计模式,GoF94),其中建议传递给策略构造函数的上下文可以是包含策略(作为成员)本身的对象。但以下方法行不通: //analysis.h class StrategyBase; class Strategy1; class Strategy2; class Analysis { ... void ChooseStrategy(); private: StrategyBase* _s; ... }; //analysis

我特别想到了策略模式(设计模式,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及其子类访问分析的数据成员

这是行不通的,因为在定义Strategy*类之前不能实例化它们。但它的定义取决于分析的定义。那你该怎么做?将ChooseStrategy替换为

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

在包含analysis.h和strategy.h的文件中进行实例化吗?这里的最佳实践是什么?

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

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

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

  • 正向声明
    Analysis
    Analysis.h
    strategies.h
  • 定义
    StrategyBase
    和子类(不要内联使用
    Analysis
    的方法)(
    strategies.h
  • 定义
    Analysis
    (可能已经使用使用策略的内联方法)(
    Analysis.h
  • 实现
    Analysis
    和策略类的非内联方法(
    Analysis.cpp

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

    我认为您需要更清楚地表达您的问题。
    \include
    从需要两个类的定义的任何源文件中删除两个头文件有什么问题?说清楚一点,你说“下面的方法行不通”,但不清楚你为什么认为它行不通;为什么你不能在
    策略中使用ctor
    策略1(分析*th)
    。hpp
    ?@Charles,新策略1(此)不会编译。你的建议听起来像我在最后所建议的,但在某些情况下,你希望在分析本身中选择策略@你可以,这不是导致错误的原因。@MattPhillips:对不起,我还是不明白。是什么阻止了您的
    #包括
    ing“strategy1.hpp”(或者
    Startegy1
    中有“analysis.cpp”定义的地方您需要完整定义的地方?或者您是否有需要帮助的特定编译错误?@Charles,您完全正确,这解决了问题。但是我反对的是,现在您有一个.cpp,它只冗余地包含其相应的.h文件(因为strategy.h包括analysis.h)。这只会让依赖项变得混乱,尤其是随着文件数量的增加。看起来他已经在这么做了,但问题并不是那么清楚。如果你所有的头文件在做其他事情之前都包含了它们的依赖项,那么你根本不需要决定顺序。至少,在你创建一个真正的循环依赖项之前,不需要这样做h点无论你在做什么,你都需要打破循环。不,这种方法的问题是它阻止了变量的一些重要用途。顺序应该确定,否则你不能同时使用A;作为数据成员和继承。两者都需要顺序的一侧,并且一起要求顺序是正确的。我不同意现在你所说的“同时数据成员和继承”是什么意思呢?同时数据成员和继承基本上是指C类:公共B{A;};那么问题在哪里呢?
    C.h
    应该包含
    #包含“A.h”
    #包含“B.h”
    ,以任意一种顺序,在这个类定义之前。谢谢。但我的问题是re 4)--我认为,在a.h之外的任何地方定义类a的方法都会使随后的代码更难找到。我试过了,但不喜欢。断言“您将始终具有循环依赖…”太强了。GoF的书中提到了三种方法,“让一个具体的策略从上下文中高效地访问它需要的任何数据,反之亦然。”(第319页)其中只有一种方法包括循环依赖。