Always running into a circular dependency

Started by
18 comments, last by Paradigm Shifter 10 years, 4 months ago

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.

Advertisement

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

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.



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


Why is that, please elaborate?

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 smile.png

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++ :D

Yo dawg, don't even trip.

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

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).

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.

Yo dawg, don't even trip.

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 smile.png

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.

Sean Middleditch – Game Systems Engineer – Join my team!

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!

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 sad.png 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!

Forward declare scene instead.

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

This topic is closed to new replies.

Advertisement