Sign in to follow this  
ill

How to have all the functions and classes know about each other properly C++

Recommended Posts

So I've worked with Java and in a package all the Classes know about each other and for classes outside you do import. In C/C++ you obviously do #include for a header file. That's all good and stuff, but now I'm having a lot of things come together in my engine before I start making the game. I got the image code and sound code working, and now making the main game engine. One particular function giving me problems right now for example is the quitGame function. It belongs to the main game controller that does the main application loop and gamestate control and all that. It should clean up all the resources and exit the application with the given error code so that if my image display function has an error it can say quitGame(EXIT_FAILURE); I tried having it so the pointer to the main game controller is an extern //this goes in the header file extern CtrlMain* ctrlMain; //this is run from the main function //create main game controller CtrlMain* ctrlMain = new CtrlMain; Then from somewhere in the application I say ctrlMain -> exitApp(EXIT_FAILURE); I get an error something like this: C:\Eclipse_Workspaces\SDL-Tutorials\illEngine_new/src/sound.cpp:273: undefined reference to `ctrlMain' C:\Eclipse_Workspaces\SDL-Tutorials\illEngine_new/src/sound.cpp:273: undefined reference to `CtrlMain::exitApp(int)' I tend to figure out how to fix these things but this one has me stuck. I'm definitely including the header files that has the extern CtrlMain* ctrlMain; definition. Also using all these global variables seems a bit sloppy to me. Is there some better way? I've read about namespaces as well. Would it be a good idea to define a namespace that contains a pointer to the main game controller and then say like engine::ctrlGame -> exitApp(EXIT_SUCCESS); I'm going to have quite a lot of these objects working together and I have experience with Java but not so much with C++ so it's getting really confusing having this all come together properly.

Share this post


Link to post
Share on other sites
I would suggest that instead of having a global instance of classes, pass pointers of the instance to classes that need to know about other classes.

For instance, if the the "Renderer" needed to know about the "Logger".


int main() {
Logger logger("logfile.txt");

Renderer renderer(&logger);

// do stuff

return 0;
}



Your initial thought might be that this seems a bit tedious to pass each class through constructors. It can be if all of your classes depend on a lot of other classes. With a careful design you can minimize class dependencies.

Share this post


Link to post
Share on other sites
OK. How exactly do you minimize class dependencies.

I basically have the main function create the main game controller.

The main game controller initializes graphics, sound, and starts the main application loop. It handles all the SDL events and stuff and controls gamestates. When I have a map running I would have a map controller holding info about the current map and controlling the in game specific stuff.

I guess I could pass in a pointer to the main game controller when I create the graphics object for example. I'm basically going to only have about 3 separate main objects that need to know about each other. If I combine them into one it wouldn't work out as smoothly since when I change resolution I'd like to destroy the graphics object and reinitialize it without having to destroy the entire game controller for example. Or when a map exits I want to just clean up only map data by simply destroying the mapController object.

Quote:
Original post by alvaro
Why don't you throw an exception instead?

That would require me to also handle all the exceptions. I am planning on doing that for errors soon but for now it just exits the game.

Anyway that doesn't solve the fact that I have other functions from other classes relying on each other. That exitApp function was just one example.

Share this post


Link to post
Share on other sites
To deal with two classes depending on each other, the following works well.


///////////////////////////
// class_a.h

class class_b;

class class_a {

public

class_a(class_b*);

void do_something();

private:

class_b* m_class_b;

};

///////////////////////////
// class_a.cpp

#include "class_a.h"
#include "class_b.h"

class_a::class_a(class_b* c) : m_class_b(c) {}

class_a::do_something() {
m_class_b->do_something_else();
}

///////////////////////////
// class_b.h

class class_a;

class class_b {

public

class_b(class_a*);

void do_something_else();

private:

class_a* m_class_a;

};

///////////////////////////
// class_a.cpp

#include "class_b.h"
#include "class_a.h"

class_b::class_b(class_a* c) : m_class_a(c) {}

class_b::do_something_else() {
m_class_a->do_something();
}





edit: should have used more distinct names then class_a and class_b... it is a bit hard to understand.

The main thing you need to know is that you cannot include the class you depend on in the header if that class also includes your header (cyclic dependency).

To get around this, you simple define the class "class class_a;" and only use pointers in the header. In the source file you include the header and can use the class.

Share this post


Link to post
Share on other sites
What exactly does

class_a::class_a(class_b* c) : m_class_b(c) {}

do?

It looks like you wrote the constructor but it does something with the : right after. I'd look it up if I knew what it was called. The confusing part is that it's followed by a colon and isn't part of the function body. It looks almost like class inheritance declarations like

class a : public b, public c
{
}


Also I see this m_something naming convention a lot. What does it mean exactly?

Share this post


Link to post
Share on other sites
It initializes the m_class_b pointer to point to what c points to. I would recommend reading about initialization lists.

The m_ prefix is often used to label member variables... It isn't necessary most of the time, I just used them so I could name the variables after the class name (since I avoid using capital letters).

Share this post


Link to post
Share on other sites
OK, thanks. Now I finally understand why half the examples I read have variables starting with m_

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this