Reputation: 23
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.
Upvotes: 1
Views: 1146
Reputation: 254501
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();
Upvotes: 1
Reputation: 2988
Extending on Christophe's answer, You are defining your .cpp file wrong. The general design approach is that
You should only have to include the relevant .h in the corresponding .cpp unless you want to include implementation specific headers.
You define the methods in the .cpp file, not the class itself unless you don't have a corresponding .h file. More reading on this came be done here: http://www.cplusplus.com/forum/articles/10627/
It is considered bad practice to have using namespace x in your .cpp files. If you want to include a namespace like that, do it in your header file.
There is probably more things wrong, but you will get rid of a lot of the dependency issues.
Upvotes: 1
Reputation: 73406
The problem is that your strategy Agressive
does not derive from Strategy
. So you know that Agressive
is a Strategy
but your compiler don't.
The strong type checking rules prevent therefore the compiler from converting blindly pointers between apparently unrelated types, here:
AI *ai(new Aggressive());
The solution is to adapt your strategies by making them inheriting publicly from from Strategy
:
class Aggressive : public Strategy {
public:
int execute();
};
Of course, you should do the same for the other strategies as well. Your code then compiles without further problems.
Upvotes: 0