Reputation: 988
The premise is: I'm making a particle system. I have a ParticleManager, which has a vector of ParticleSystem objects, which has a vector of type Particle. However, I also have the class Snowball, which inherits from Particle, and it has a ParticleSystem of it's own, as it leaves a trail of particles.
#pragma once
#include "ParticleSystem.h"
class Snowball : public Particle
{
private:
ParticleSystem ps;
public:
Snowball(){};
Snowball(Point2D pos, RECT* viewport);
void Update();
void Draw(GraphicsM * pGraphicsModule);
};
This is the Snowball.h file, and the ParticleSystem one just has #include "Snowball.h" at the top, and uses Snowball throughout, as any given Particle can be a Snowball. How do I resolve this, either through a change of architecture or the order of code?
Upvotes: 0
Views: 79
Reputation: 9393
One option: instead of giving Snowball a member of type ParticleSystem, give it a pointer to ParticleSystem (preferably a shared_ptr or unique_ptr to preclude memory leaks). Then you don't need to #include ParticleSystem.h in Snowball.h; you just need to forward-declare it. Snowball's constructor would then need to move to the .cpp file and instantiate a new ParticleSystem there to store in the pointer.
Something like:
// Snowball.h
class ParticleSystem;
class Snowball
{
private:
std::shared_ptr<ParticleSystem> ps;
public:
Snowball();
// rest the same
};
// Snowball.cpp
#include "Snowball.h"
#include "ParticleSystem.h"
SnowBall::SnowBall()
: ps(std::make_shared<ParticleSystem>())
{
}
// rest the same except for ps. becoming ps->
Upvotes: 2
Reputation: 2802
The other answers provide a good demonstration of how to work round the issue. However, have you considered restructuring your code so this isn't necessary? Normally, circular dependencies will cause other issues later.
An alternative structure is you could use composition instead of inheritance.
The circular dependency comes from the particle system using particles, but the particle also using the particle system. This is because snow ball is a particle.
Instead, you could have your snowball contain an instance of a particle and an instance of the particle system. This is called composition as you are composing your snowball out of a particle and a particle system.
This way Particle depends on Particle System and snowball depends on both and hence no circular dependency.
Upvotes: 0
Reputation: 96569
In cases when you need several classes that use each other as complete type, you can use something like this:
class TestClass1;
class TestClass2;
class TestClass1
{
int val;
TestClass2 foo();
};
class TestClass2
{
int val;
TestClass1 foo();
};
TestClass2 TestClass1::foo()
{
/* ... */
}
TestClass1 TestClass2::foo()
{
/* ... */
}
Upvotes: 0