策略模式 - C++

Strategy Pattern - C++

我在为我的项目实施策略模式时遇到问题。我创建了所有必要的文件,但是我在 main 中的新调用出现错误,因为我似乎无法将策略初始化为我想要的。

Strategy.h

/*All the classes that implement a concrete strategy should use this
The AI class will use this file as a concrete strategy
*/
using namespace std;
class Strategy{
public:
    //Method who's implementation varies depending on the strategy adopted
    //Method is therefore virtual
    virtual int execute() = 0;
 };

我的三个策略 Aggressive.h

#pragma once
#include <iostream>
#include "Strategy.h"

class Aggressive{
   public:
      int execute();

 };

Aggressive.cpp

#pragma once
#include <iostream>
#include "Strategy.h"
using namespace std;

class Aggressive : public Strategy{
  public:
      Aggressive(){}

      int execute(){
        cout << "The defensive player chooses to adopt an aggressive play-                             style" << endl;
        return 0;
    }

};

Defensive.h

#pragma once
#include <iostream>
#include "Strategy.h"

class Defensive{
  public:
     int execute();

};

Defensive.cpp

#include <iostream>
#include "Strategy.h"
using namespace std;

 class Defensive : public Strategy{
    public:
       int execute(){
        cout << "The defensive player chooses to adopt a defensive play-style" << endl;
    }
 };

AI.h

#pragma once
#include "Strategy.h"

class AI{
  public:
    AI();
    AI(Strategy *initStrategy);
    void setStrategy(Strategy *newStrategy);
    int executeStrategy();

};

AI.cpp

#pragma once
#include "Strategy.h"
#include "AI.h"
#include "Aggressive.h"
#include "Defensive.h"


using namespace std;

 class AI{
   private:
       Strategy *strategy;
   public:
      AI(){}
         //Plugs in specific strategy to be adopted
      AI(Strategy *initStrategy){
          this->strategy = initStrategy;
      }
      void setStrategy(Strategy *newStrategy){
          this->strategy = newStrategy;
      }
      //Method that executes a different strategy depending on what 
      //strategt was plugged in upon instantiation.
       int executeStrategy(){
          return this->strategy->execute();
      }
  };

还有我的临时 driver,它与新的有问题 StrategyDriver.cpp

#pragma once
#include "AI.h"
#include "Strategy.h"
#include "Aggressive.h"
#include "Defensive.h"
#include "Random.h"
using namespace std;

int main(){
   AI *ai(new Aggressive());
    ai->executeStrategy();  
}

如果有人发现我的代码存在问题,将不胜感激。我不完全确定如何将新 ai 初始化为已实施的特定策略。

问题在于您的策略 Agressive 并非源自 Strategy。所以你知道 Agressive Strategy 但你的编译器不知道。

因此,强类型检查规则可防止编译器在明显不相关的类型之间盲目地转换指针,此处:

AI *ai(new Aggressive());

解决方案是调整您的策略,使它们公开继承自 Strategy

class Aggressive : public Strategy {
public:
    int execute();

};

当然,您也应该对其他策略执行相同的操作。然后您的代码可以编译而不会出现其他问题。

您试图定义相同的 class 两次,一次在 header 中,一次在源文件中。 main 只看到 header 中的定义,它没有继承自 Strategy,因此出现错误。

header 需要定义 class,声明其所有 parent classes 和成员:

#pragma once
#include "Strategy.h"

class Aggressive : public Strategy{
public:
    Aggressive(){}
    int execute();
};

并且源文件只定义了 header:

中未定义的所有成员
// no header guard (#pragma once) - that's just for headers
#include <iostream>
#include "Aggressive.h"  // include the class definition
using namespace std;

int Aggressive::execute(){
    cout << "The defensive player chooses to adopt an aggressive play-                             style" << endl;
    return 0;
}

通过这些更改,class 定义将在 main 中使用的地方可用,因此从 Aggressive* 到 base-class 指针的转换 Strategy* 将被允许。您需要对其他 classes 进行类似的更改才能构建程序并 运行 正确。

最后,main 想要创建一个 AI object(可以用 Strategy* 初始化)而不是 AI* 指针(可以't).

AI ai(new Aggressive());
ai.executeStrategy();

扩展 Christophe 的回答,您定义的 .cpp 文件有误。一般的设计方法是

  1. 你只需要在相应的.cpp中包含相关的.h,除非你想包含具体实现 headers。

  2. 您在 .cpp 文件中定义方法,而不是 class 本身,除非您没有对应的 [=21= .h 文件。在这里可以进行更多阅读:http://www.cplusplus.com/forum/articles/10627/

  3. .cpp 文件中 using namespace x 被认为是不好的做法。如果你想包含这样的名称空间,请在你的 header 文件中进行。

可能还有更多错误,但您会摆脱很多依赖性问题。