C++ 你如何通过';这';作为没有循环依赖项的另一个类构造函数的参数?
我特别想到了策略模式(设计模式,GoF94),其中建议传递给策略构造函数的上下文可以是包含策略(作为成员)本身的对象。但以下方法行不通: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
//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页)其中只有一种方法包括循环依赖。