Search code examples
c++design-patternsstrategy-pattern

Strategy Pattern - C++


I'm having an issue implementing a strategy pattern to my project. I created all the files necessary, however I am getting an error with my new call in main as I can't seem to initialize a strategy to what I want.

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;
 };

My three strategies 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();
      }
  };

And my temporary driver, which has an issue with new 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();  
}

If anyone sees the issue with my code, any help would be greatly appreciated. I'm not entirely sure on how to initialize the new ai to specific strategies that were implemented.


Solution

  • You're trying to define the same class twice, once in the header and once in a source file. main only sees the definition in the header, which doesn't inherit from Strategy, hence the error.

    The header needs to define the class, declaring all its parent classes and members:

    #pragma once
    #include "Strategy.h"
    
    class Aggressive : public Strategy{
    public:
        Aggressive(){}
        int execute();
    };
    

    and the source file just defines any members that weren't defined in the 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;
    }
    

    With these changes, the class definition will be available where it's used in main, so the conversion from Aggressive* to a base-class pointer Strategy* will be allowed. You'll need to make similar changes to the other classes for the program to build and run correctly.

    Finally, main wants to create an AI object (which can be initialised with a Strategy*) not an AI* pointer (which can't).

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