C++ Scope Question

Started by
4 comments, last by m0ng00se 16 years, 2 months ago
I have a scope issue with my AI code. My main message handler (Win32 API) calls my AI code which loads my AI database into memory, vectors through it to get a keyword match then exits back to the message handler which then calls the message loop in my animation code. All the AI stuff is part of the AI class (the only proper C++ class I use) and when the code returns to the Win message handler it goes out of scope and deconstructs everything, including the database. So next time through the loop I load it again. I didn't think it was an issue because I stored results in external variables that all my code can access. I just realised however that my AI code is giving crap because it loses pointers to context of where it's at in the database. I can put all these into external variables too but that is such bad coding. I hate using external global variables. My question is a pure C++ one. How do I prevent all the AI code from being deconstructed each time through the loop... or how do I give the AI class global scope or what else can I do to fix this issue? Like it's great that it cleans up memory the way it should and leaves no objects laying around but it would be so much easier if I could just load the database once at initialization and keep all the class variables etc in memory for the entire runtime. m0ng00se
Advertisement
Always place your variables at the innermost scope at which they can live. In your case, they should be placed in the scope which contains the loop (possibly another statement, loop, or perhaps a function) instead of the scope of the loop.
There should be three phases to your code. init, game loop, cleanup. The ai construction and initialization should happen before you enter the game loop.
Hi stonemetal,

yes I totally agree and that's the problem. Even in init it still deconstructs when it returns to run the main loop.

All the AI code is a member of my AI class. All the loading, vectoring, last reply, short answer etc, etc.

So I have to call it like:

//Init
AIClass AIObject;
AIObject.load_Database(); //loads and works fine

//Main Loop
//Not part of AI class

Do_Other_Stuff(); //oops database gone

//No good because AIObject has been destroyed.

Here is psuedocode of main

//Init
Load Database and print sprite opening comment
Run opening animation

//Main Loop
Get user response and run matching animation // not part of AI class
Find keyword to user response in database //oops database gone (is AI Class)

So i reload the database but I've lost all my pointer values to previous response etc.

m0ng00se
So, right now, we have something like:

Make an AIClass named AIObject.AIObject, load the database.Tell the user we are doing something, and play an animation.While (command: read from input) is not (abort):  Play corresponding animation.  AIObject, look up the command in the database (oops, it's gone?)


The problem is the word the. We refer to some database that is created locally by AIObject in a function, and then ceases to exist. It needs to be remembered somewhere.

Where?

Not globally, because that prevents reuse. That just makes the word "the" problematic for another reason: because we emphasize the idea of having only one database, which makes no sense.

Instead, we store it in the object. That is, make a data member:

Make an AIClass named AIObject.AIObject, load your database.Tell the user we are doing something, and play an animation.While (command: read from input) is not (abort):  Play corresponding animation.  AIObject, look up the command in your database.


Except, dealing with this database is unnecessarily complicated for the calling code. It should not have to worry about databases; that's the AIClass' job - i.e., one of the reasons we created the class in the first place.

Instead, we just tell the AIClass the minimum it needs in order to do the setup. We load the database automatically, as a part of creating the object, by using the constructor. We'll pass a file name (the name of the database file) to the constructor, so that the constructor knows where to find the necessary information), and we'll forget about grabbing the database member to pass to the "lookup" function: objects always implicitly have access to their own members, and should be in control of them.

Make an AIClass named AIObject, whose database is read from "xxx.txt".Tell the user we are doing something, and play an animation.While (command: read from input) is not (abort):  Play corresponding animation.  AIObject, look up the command.


If you don't know how to apply this to your code, I'm going to have to see what you have, in order to indicate the necessary changes properly.
Thanx Zahlman...

Yes I understand exactly what you mean. Certainly better than using globals like I was going to do as a quick and dirty fix.

Also as you correctly stated the AI class exists to look after it's own objects properly so I don't need to worry about them elsewhere.

I don't mind posting the relevant code but I'll have a go at implementing what you suggested first. I had a lovely program with nice objects that cleaned up after themselves and functions returning values properly and no memory leaks. Everything got handled properly by the AI Class but that was all a console program just for building the AI code and testing it.

Then I added the Win32 GUI API and all the animation stuff and had to combine three different main control loops, the AI one, the Win32 one and the animation one. My nice AI Class got split up all over the place to make room for other control loops.

Now it's just plain nasty but I'm slowly getting it back on track. I would have liked to derive everything from a base AI Class but trying to incorporate 3rd party SDK library functions (animation) into my own classes was too hard for me because they have pre-existing classes of their own.

I'll let you know how I get on with what you suggested.

m0ng00se

This topic is closed to new replies.

Advertisement