View more

View more

View more

### Image of the Day Submit

IOTD | Top Screenshots

### The latest, straight to your Inbox.

Subscribe to GameDev.net Direct to receive the latest updates and exclusive content.

# Always running into a circular dependency

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

19 replies to this topic

### #1PragmaOnce  Members

Posted 29 November 2013 - 07:33 AM

Hi guys.

So whenever I try to make a game I run into a problem where a circular dependency occurs between the scene or level holding my game objects and the game objects that need access to the level. I am sure this can be easily solved because my architecture is structured wrong but I just can't seem to think of an efficient solution. I'll roughly show what I have (just the parts that are causing the dependency).

Scene.h

#include "ObjectList.h"

class Scene : public EventListener
{
public:
ObjectList objectList; // This holds all the entities that are currently active in a particular scene/level.
};


ObjectList.h

#include "Entity"

class ObjectList
{
private:
std::vector<Entity*> objectList;
};


Entity.h

#include "Scene.h"

class Entity : public sf::Sprite, public EventListener
{
protected:
Scene *gameWorld;
};

Edited by PragmaOnce, 29 November 2013 - 07:46 AM.

### #2Samith  Members

Posted 29 November 2013 - 08:17 AM

POPULAR

Since Entity only has a pointer reference to Scene, you can forward declare Scene. That way you won't have to include scene.h and you'll avoid the circular dependency problem. A forward declaration looks like this:

class Scene;

This lets the compiler know that the type Scene exists, but doesn't tell it anything else. Scene can be declared elsewhere without issue.

Forward declaration is fairly common. Sometimes you just need two types to know about each other!

### #3rozz666  Members

Posted 29 November 2013 - 10:35 AM

Why does an Entity has to know about the Scene?

### #4Dragonsoulj  Members

Posted 29 November 2013 - 11:28 AM

Look up guard statements.

#ifndef ENTITY_H
#define ENTITY_H

And at the end of the header:

#endif

### #5Dante12129  Members

Posted 29 November 2013 - 12:16 PM

Why does the entity need to know about the scene?

Also, you shouldn't be inheriting from sf::Sprite. Make it a member and, if you want to use your class like the sprite, inherit from sf::Drawable and sf::Transformable. You'll need to override the draw method, and there are a few things that the Sprite has that aren't in either of those (color, bounds, and texture/texture rects).

### #6PragmaOnce  Members

Posted 29 November 2013 - 01:00 PM

Look up guard statements.

#ifndef ENTITY_H
#define ENTITY_H

And at the end of the header:

#endif

I use #pragma once.

I didn't include it with my examples because it has nothing to do with the problem at hand. Those classes are actually filled with members and methods but I thought I would leave out any code that has nothing to do with the circular dependency, to make the problem easier for others to understand.

Why does an Entity has to know about the Scene?

Because the Scene is going to hold the list of entities found in a particular level. I was thinking I might need it later to implement some logic, for example:

// Inside explosion_object, this is purely psuedo
Explode()
{
}



Also, you shouldn't be inheriting from sf::Sprite

Thanks for the tip on forward declarations. I have read about them but I always thought it was bad practice to do it, but if you say it's fairly common I guess it's a solution

Edited by PragmaOnce, 29 November 2013 - 01:09 PM.

### #7Samith  Members

Posted 29 November 2013 - 01:09 PM

That's why I use
#pragma once

One small thing about #pragma once is that it's technically not part of the standard, and though it's widely supported (I don't think I've ever seen a compiler that doesn't support it) people will often use include guards after the #pragma once, just in case #pragma once isn't supported.

Edited by Samith, 29 November 2013 - 01:09 PM.

### #8Dragonsoulj  Members

Posted 29 November 2013 - 01:15 PM

I use #pragma once.

I didn't include it with my examples because it has nothing to do with the problem at hand. Those classes are actually filled with members and methods but I thought I would leave out any code that has nothing to do with the circular dependency, to make the problem easier for others to understand.

Since the topic appeared to be circular dependency, making a note about using guards or #pragma once would have contributed to the understanding, as that tends to be one portion of usual circular dependency issues.

### #9PragmaOnce  Members

Posted 29 November 2013 - 01:20 PM

That's why I use
#pragma once

One small thing about #pragma once is that it's technically not part of the standard, and though it's widely supported (I don't think I've ever seen a compiler that doesn't support it) people will often use include guards after the #pragma once, just in case #pragma once isn't supported.

Yes, I know it's only a directive for compilers. Since I am a mere novice, working alone, on a project that no one else will see... I figured that if my compiler supports it, it reduces the chance of bugs, and does not involve as much typing

I use #pragma once.

I didn't include it with my examples because it has nothing to do with the problem at hand. Those classes are actually filled with members and methods but I thought I would leave out any code that has nothing to do with the circular dependency, to make the problem easier for others to understand.

Since the topic appeared to be circular dependency, making a note about using guards or #pragma once would have contributed to the understanding, as that tends to be one portion of usual circular dependency issues.

Ah I see, forgive my lack of experience. I didn't realize that it could cause dependency issues. Thank you

### #10Dragonsoulj  Members

Posted 29 November 2013 - 01:25 PM

Dragonsoulj, on 29 Nov 2013 - 2:15 PM, said:

PragmaOnce, on 29 Nov 2013 - 2:00 PM, said:

I use #pragma once.

I didn't include it with my examples because it has nothing to do with the problem at hand. Those classes are actually filled with members and methods but I thought I would leave out any code that has nothing to do with the circular dependency, to make the problem easier for others to understand.

Since the topic appeared to be circular dependency, making a note about using guards or #pragma once would have contributed to the understanding, as that tends to be one portion of usual circular dependency issues.

Ah I see, forgive my lack of experience. I didn't realize that it could cause dependency issues. Thank you

Not always the case, but one potential issue. I ran into this a few times myself.

Just a potential thought to this issue, why not just pass the Scene to your Explode function and see if that removes the issue?

### #11PragmaOnce  Members

Posted 29 November 2013 - 01:36 PM

Because currently the Explode function does not exist :/ I have a tendency to go into a "What if.. " mindset when programming. I could even make an EXPLOSION_EVENT with those parameters and make the scene register to it. That way the scene will handle the explosion and my entities are oblivious to the world they are in.

Basically, i'm just scared that at some or other point my Entities are going to need something and my scene class is "global" enough to be able to respond to anything the Entities might want. But... now that I really think about it, events will be able to keep things together. If not, then I guess i'll have to do some refactoring.

It's really hard for me to plan things out because I am afraid of having to refactor. I know code is not supposed to be completely set in stone but I can't stop myself from being over cautious to eliminate the chances of redoing something.

### #12Waterlimon  Members

Posted 29 November 2013 - 02:56 PM

In this particular case, the objects storing a pointer to the scene is redundant and a waste of memory. The scene is implicit in the objects being within the scene. Thus you should pass the scene to the methods of the objects that require the scene.

A potential downside with explicitly passing the scene to the methods is, well, that its explicit. When you store it in the object, the object "implicitly" knows which scene you are talking about, since you set it when creating the object. When you pass the scene as a parameter, the scene is still implicit, except that C++ does not have the capability to implicitly pass the scene, and thus it must be done manually for each and every method call. This might be enough to just keep it as a member variable, since your game code will be less cluttered with fairly redundant information.

o3o

### #13Satharis  Members

Posted 29 November 2013 - 03:23 PM

General rules of thumb I use are:

• If it's a pointer or a reference, forward declare it.
• If its something complex like a bunch of typedefs(as Microsoft is famous for) just give up and include the file.
• If the class/struct is a member, include the file.

That fixes most issues.

In your case I would question why both the scene and the object list need to know about entities as well as the former including the later of the two. Of course if your object can exist without a scene then you probably should have the scene as a pointer, which you do. So declare class Scene;

Treat header files as vague, treat cpp files as where you include the meat of how to work with objects.

Edited by Satharis, 29 November 2013 - 03:23 PM.

### #14boogyman19946  Members

Posted 29 November 2013 - 05:15 PM


Also, you shouldn't be inheriting from sf::Sprite

Thanks for the tip on forward declarations. I have read about them but I always thought it was bad practice to do it, but if you say it's fairly common I guess it's a solution

You shouldn't be inheriting from any classes that don't include a virtual destructor. If you cast the derived object into its base class and call the object's destructor, chances are good that the derived destructor will not be called. That is at least what I learned from Effective C++

### #15Dante12129  Members

Posted 29 November 2013 - 05:26 PM

Actually, Sprite does have a virtual destructor because sf::Drawable has one. Here are some link  on the SFML about inheriting from sf::Sprite.

### #16RobTheBloke  Members

Posted 29 November 2013 - 05:28 PM

Look up guard statements.

His user name is pragma once - I reckon he's aware of how to use them ;)  #defined sentry nonsense is only useful if you're targeting an ancient compiler, or because you are doing something a bit freaky with redefined macros (which would probably be better served in template form)

It's really hard for me to plan things out because I am afraid of having to refactor. I know code is not supposed to be completely set in stone but I can't stop myself from being over cautious to eliminate the chances of redoing something.

The spend less time thinking about the code, and make it easy enough to throw away!

You will inevitably be refactoring at some point - it's the nature of the game really. Being aware of potential problems in the future is a good thing (makes you aware of areas to not invest too heavily in, since you'll probably need to rework at a later date), but coding for every possible eventually is not (a.k.a. second system syndrome).

### #17boogyman19946  Members

Posted 29 November 2013 - 05:35 PM

Actually, Sprite does have a virtual destructor because sf::Drawable has one. Here are some link  on the SFML about inheriting from sf::Sprite.

Nice catch! I checked out Sprite.hpp and didn't see it declare a destructor so I thought it didn't have one.

### #18SeanMiddleditch  Members

Posted 01 December 2013 - 12:04 AM

Thanks for the tip on forward declarations. I have read about them but I always thought it was bad practice to do it, but if you say it's fairly common I guess it's a solution

It's quite the opposite.  You should use them everywhere you possibly can instead of including headers in headers.  This will greatly assist your compilation/iteration times with normal build systems, especially if you also avoid the STL as much as possible.  If you habitually use forward declarations and avoid header includes in other headers unless you are forced to you'll find you tend to design better classes, too.

Game Developer, C++ Geek, Dragon Slayer - http://seanmiddleditch.com

C++ SG14 "Games & Low Latency" - Co-chair - public forums

Wargaming Seattle - Lead Server Engineer - We're hiring!

### #19dejaime  Members

Posted 03 December 2013 - 12:56 PM

If you want to avoid this circular dependency, you can declare that "scene *gameworld" as "void *miscdata". It'd add up reusability and free you from this circular dependency, under the cost of increased complexity. But you really should rethink your architecture; as a teacher once told me, if programmers can't understand your architecture, it's a bad one. Given that more people asked the same question i would, I am not the only one!

Posted 03 December 2013 - 04:04 PM

Don't do that! If you delete it through a void* without a cast no destructor will be called! EDIT: plus you need to cast it everywhere you use it unless you are just taking the address EDIT2: And you could cast it to anything you want really with a C-style cast and the compiler will assume you know what you are doing!