I have a PieceStrategy class:
#include "QueenStrategy.cpp"
class PieceStrategy {
void promoteToQueen() {
this = new QueenStrategy();
}
}
And I have a QueenStrategy class which inherits from it:
#include "PieceStrategy.cpp"
class QueenStrategy : public PieceStrategy {}
Now arises the circular includes problem. But in this case, I cannot use forward declaration.
What should I do?
You should not include cpp files, but headers
You must not assign to this
Choose another design. You should not try to modify the strategy but select another one for the actual object, that uses that strategy.
piece.hpp
#include "strategy.hpp"
class Piece
{
std::unique_ptr<Strategy> strategy;
public:
static Piece Pawn();
void PromoteToQueen();
};
piece.cpp
#include "pawn.hpp"
#include "queen.hpp"
Piece Piece::Pawn()
{
Piece p;
p.strategy = std::make_unique<PawnStrategy>();
return p;
}
void Piece::PromoteToQueen()
{
strategy = std::make_unique<QueenStrategy>();
}
Related
I am getting a C2504 compilation error in PlayerController.h saying that my base class (Updateable) is undefined. I have searched for several hours for a solution to a circular inclusion with inheritance problem and their solutions are to remove the circular inclusions and jsut use a forward declaration. As far as I understand, this works if no methods from the forward declared class are called. However, in my program my Updateables class calls a method on its member inherited gameObject object and the GameObjects also call methods on their member Updateables. Because of this, Updateables need to include GameObject.h and GameObjects need to include Updateables.h. This leads to a C2504 in PlayerController.h saying that the base class Updateable can not be found.
Here are my relevant classes:
Component.h
#pragma once
#include "Vector3.h"
class GameObject;
class Component {
public:
GameObject* gameObject = nullptr;
Component();
};
Component.cpp
#include "Component.h"
Component::Component() {}
Updateable.h
#pragma once
#include "Component.h"
#include "GameObject.h"
class GameObject;
class Updateable : public Component {
public:
~Updateable();
virtual void update() = 0;
};
Updateable.cpp
#include "Updateable.h"
Updateable::~Updateable() {
if (gameObject) {
gameObject->removeUpdateable(this);
}
}
GameObject.h
#pragma once
#include "Updateable.h"
#include "GameManager.h"
class Updateable;
class GameObject {
public:
GameObject();
~GameObject();
void runUpdateables();
void addUpdateable(Updateable* updateable);
void removeUpdateable(Updateable* updateable);
private:
vector<Updateable*> updateables;
};
GameObject.cpp
#include "GameObject.h"
GameObject::GameObject() {
updateables = vector<Updateable*>();
GameManager::addGameObject(this);
}
GameObject::~GameObject() {
GameManager::removeGameObject(this);
}
void GameObject::runUpdateables() {
for (unsigned int i = 0; i < updateables.size(); i++) {
updateables[i]->update();
}
}
void GameObject::addUpdateable(Updateable* updateable) {
updateables.push_back(updateable);
updateable->gameObject = this;
}
void GameObject::removeUpdateable(Updateable* updateable) {
auto it = find(updateables.begin(), updateables.end(), updateable);
if (it != updateables.end()) {
updateables.erase(it);
}
}
PlayerController.h
#pragma once
#include "Updateable.h"
//#include "GameObject.h"
#include "Input.h"
class Updateable;
class PlayerController : public Updateable {
public:
float speed = 5.0f;
void update();
};
PlayerController.cpp
#include "PlayerController.h"
void PlayerController::update() {
float x = 0;
if (Input::getKeyDown(GLFW_KEY_A)) {
x = -speed;
}
if (Input::getKeyDown(GLFW_KEY_D)) {
x = speed;
}
cout << x << endl;
gameObject->getRigidBody()->velocity.x = x;
//yes this is a method in GameObject that I removed from this post
//because it would take up more space, rigidbody.h does not create
//a circular dependency
}
GameManager.h
#pragma once
#include "GameObject.h"
#include "PlayerController.h"
class GameManager {
public:
static void init();
static void addGameObject(GameObject* go);
static void removeGameObject(GameObject* go);
static void onFrame();
private:
static vector<GameObject*> gameObjects;
static GameObject* box;
GameManager.cpp
#include "GameManager.h"
vector<GameObject*> GameManager::gameObjects;
GameObject* GameManager::box;
void GameManager::init() {
gameObjects = vector<GameObject*>();
box = new GameObject();
box->addUpdateable(new PlayerController());
}
void GameManager::addGameObject(GameObject* go) {
gameObjects.push_back(go);
}
void GameManager::removeGameObject(GameObject* go) {
auto it = find(gameObjects.begin(), gameObjects.end(), go);
if (it != gameObjects.end()) {
gameObjects.erase(it);
}
}
void GameManager::onFrame() {
for (unsigned int i = 0; i < gameObjects.size(); i++) {
gameObjects[i]->runUpdateables();
}
}
Here is the exact error message: Error C2504 'Updateable': base class undefined Basic Platformer c:\users\default.sixcore-pc\documents\visual studio 2015\projects\basic platformer\basic platformer\playercontroller.h 9
A lot of your files have both #include "Class.h" and class Class; declarations. You never need both; use one or the other.
A definition of a class X must be visible when:
accessing the members of X
creating an object of type X
defining a class derived from X
using X as a template argument to a template which requires the corresponding template parameter to be a complete type (such as what standard library containers require of their element type). Note that this applies when using X, not X*.
In other cases (such as creating a pointer to X or declaring a function taking of returning X), a non-defining declaration (class X;) is enough.
Using these rules (plus moving function bodies from headers to source files when necessary), you can solve any circular dependency issues.
To directly address your files as presented:
Updateable.h does not need to #include "GameObject.h". It doesn't even need the forward declaration of GameObject.
GameObject.h doesn't need any of the two #includes in it.
GameManager.h doesn't need any #includes. It needs a declaration of class GameObject; though.
Descendant class must know the full definition of the base class. Forward declaration is not enough and useless.
Suppose I wrote some code like this:
// myinterface.h
struct MyInterface { void foo()=0; };
// mydefault.h
#include "myinterface.h"
struct MyDefaultImplementation : MyInterface { void foo(){} };
// main.cpp
#include "myinterface.h"
#include "mydefault.h" // (X)
int main(){
MyInterface* x = new MyDefaultImplementation(); // (X)
x->foo();
}
I can provide a different implementation of the interface easily, but I need to change the lines where I create the instance and of course the include (X).
Is it possible to replace the implementation of the interface without changing existing code?
Just to clarify: of course with the above code it is not possible, but can I change it somehow, such that later when I want to switch to another implementation of the interface I dont have to change it?
The closest I could find is this, but thats java :(
Btw the example is very much simplified, but also in my actual code, there is only a single line in the code, where I create the instance.
Use a factory approach, eg:
myinterface.h
struct MyInterface
{
virtual ~MyInterface() {}
virtual void foo() = 0;
};
MyInterface* createMyInterface();
main.cpp
#include "myinterface.h"
int main()
{
MyInterface* x = createMyInterface();
x->foo();
delete x;
}
Then you can make createMyInterface() create whatever struct type you need, eg:
mydefault.h
#include "myinterface.h"
struct MyDefaultImplementation : MyInterface
{
void foo(){}
};
myinterface.cpp
#include "mydefault.h"
MyInterface* createMyInterface()
{
return new MyDefaultImplementation;
}
Trying to pass a parent class object to a child class object so that the child class object has control over the parent class object's methods.
This is however resulting in header related issues.
I've tried forward declaring one of the classes but it seems whatever class is declared first always has trouble reading from the class declared below.
Both errors refer to Device' constructor where try to call dm's hello world method, they are:
Use of undefined type 'DeviceManager'
Left of '->HelloWorld' must point to class/struct/union/generic type
...
//main.cpp
#include "parent.h"
void main()
{
cout << "Created DeviceManager\n";
DeviceManager* deviceManager = 0;
deviceManager = new DeviceManager;
cout << "Giving DeviceManager a device\n";
deviceManager->p = new Device(deviceManager);
cout << "Giving Device a reference to DevicenManager\n";
deviceManager->Share();
}
...
class DeviceManager;
class Device
{
public:
Device(DeviceManager* manager)
{
dm = 0;
this->dm = manager;
this->dm->HelloWorld();
}
DeviceManager* dm;
};
//device manager
class DeviceManager
{
public:
DeviceManager()
{
p = 0;
}
void HelloWorld()
{
//if this calls we know the child has control over the parent.
cout << "Hello World";
}
Device* p;
};
Yes.
To solve circular dependencies with class member and function declarations, you can forward-declare a class:
class A;
class B {
A *a;
};
class A {
B *b;
};
To define class member functions that access members of the other class, you must define the function after the other class has been defined:
class B;
class A {
public:
void f(B &arg);
};
class B {
public:
void g(A &arg);
};
void A::f(B &arg) {
arg.g(*this);
}
void B::g(A &arg) {
arg.f(*this);
}
Usually, in a C++ project, you wouldn't even encounter this problem: You would put function definitions, i.e. implementations, into .cpp files, while putting the class definitions into header files. Class forward declarations, if neccesary, could be put into their own header files that are included by all headers that need them.
A full example of how you would split the above code into multiple files:
a.cpp
#include "a.h"
#include "b.h"
void A::f(B &arg) {
arg.g(*this);
}
b.cpp
#include "b.h"
#include "a.h"
void B::g(A &arg) {
arg.f(*this);
}
a.h
#ifndef _A_H_
#define _A_H_
#include "forward_declarations.h"
class A {
public:
void f(B &arg);
};
#endif //_A_H_
b.h
#ifndef _B_H_
#define _B_H_
#include "forward_declarations.h"
class B {
public:
void g(A &arg);
};
#endif //_B_H_
forward_declarations.h
#ifndef _FORWARD_DECLARATIONS_H_
#define _FORWARD_DECLARATIONS_H_
class A;
class B;
#endif //_FORWARD_DECLARATIONS_H_
As a general rule of thumb, if you need to forward-declare a class, you might have misdesigned something and should think about whether there is a better way (but there also are perfectly valid use cases that require class forward declarations).
If you don't understand my #ifndef, #define and #endif preprocessor lines: These are header guards, and should be used with all files that are included somewhere else, exception you know precisely what you're doing. Believe me. You'll regret ommiting one.
If your problem is cyclic dependancy, like this:
// DeviceManager.h
#include "device.h"
class DeviceManager
{
DeviceManager(Device& device) {}
};
// Device.h
#include "DeviceManager.h"
class Device
{
Device(DeviceManager& manager) {}
};
You can solve the problem be forward declaring one of the classes, and passing the object by pointer.
// Device.h
//#include "DeviceManager.h"
class DeviceManager;
class Device
{
Device(DeviceManager* manager) {}
};
I am having an issue with two classes that reference each other. I have attempted to use an interface to resolve the issue, but run into other problems such as class re-definition. I am just not sure how to do this properly.
here is an example of what I have going on. Note: I have taken out all the extra properties and methods that are not actually affecting this issue. How can I redo these without causing class re-definitions and without the circular reference. If you can, please use this example as a template for a correct layout of the statements.
// componentClass.h
//#include "controlClass.h" - Would cause a circular reference
namespace test
{
//component class
public ref class componentClass sealed : Component
{
internal:
componentClass(controlClass ^control);
private:
controlClass ^_control;
};
}
// controlClass.h
#include "componentClass.h";
namespace test
{
//control class
public ref class controlClass: Control
{
public:
controlClass();
private:
componentClass ^_componentClass;
};
}
// controlClass.cpp
#include "controlClass.h"
controlClass::controlClass()
{
_componentClass = gcnew componentClass(this);
}
// componentClass.cpp
#include "componentClass.h"
componentClass::componentClass(controlClass ^control)
{
_control = control;
}
Generally the easiest way to resolve this issue is to put both class declarations inside of one header file, and forward-declare the second one. For example:
namespace test
{
// Forward declaration of controlClass
ref class controlClass;
//component class
public ref class componentClass sealed : Component
{
internal:
componentClass(controlClass ^control);
private:
controlClass ^_control;
};
//control class
public ref class controlClass: Control
{
public:
controlClass();
private:
componentClass ^_componentClass;
};
}
It's possible to accomplish this with multiple header files, but there are caveats and complexities that are eliminated by using a single header file.
You can continue to provide the implementation of each class in a different source file without problems.
I stuck at defining a static pointer inside one of my class which is pointing to another class
here is the schema of what I've done :
#busineslogic.h
class BussinesLogic {
private :
static Samenamespace::otherclass_DataLogic::clsDL *DL;
};
#busineslogic.cpp
samenamespace {
businessnamespace{
clsBL{
Samenamespace::businessnamespace::clsBL *Samenamespace::businessnamespace::clsBL::DL;
}
}
}
so with above definition I'll get error every time I compile the code , I've tried several other ways to overcome this problem but the face of the errors gonna change not the whole problem.
I want to know how can I access to another class from my class in such a static way I mean something like above example , how should I change my code ? or should add something extra?
// header:
#include <other/b.hpp>
namespace example {
struct A {
static other::B* name;
};
}
// implementation: (.cpp)
namespace example {
other::B* A::name;
}
Edit: With the cleanup of the question, it looks like B and A are in the same namespace, which would simplify the example:
// header:
#include <example/b.hpp>
namespace example {
struct A {
static B* name;
};
}
// implementation: (.cpp)
namespace example {
B* A::name;
}