Advanced C++ Help Request

Started by
10 comments, last by BrianMJC 17 years, 12 months ago
Greetings, I am having difficulty with calling class functions through a class array of class function pointers. Coming from a C background, I've recently started using more of the full C++ language. I've successfully compiled past programs with the same situation sans class scope (e.g. using regular functions and a regular array of function pointers). But I decided to be a good C++ programmer this time and encapsulate my state machine functions and data into a 'stateobj' class object. I had enough trouble with getting the initialization of the array of function pointers to successfully compile with that (horrific!) scope syntax you see below (in the .cpp file), but the Run() class function is generating a compiler error, specifically the "_proc[_numStates]()" segment. I'm using MS Visual C++ .NET 2003 on a WinXP system, and receive "Compiler Error C2064: term does not evaluate to a function taking 0 arguments." The MS help on that error suggests I haven't declared the array of function pointers correctly (MS examples: declaring "int i, j; i = j();" or "int i, *k; i = k();"). But it looks fine to me, except maybe the scope is off somehow? I'm still a bit fuzzy on working with scope syntax (getting the array declarations was a lucky guess!). Your help is much appreciated, thanks! Here's the relevant code:
// Within .h file...
class stateobj
	{
	public:
		enum state { _error, _init, _wait, _shutdown, _numStates };
		stateobj () { _curState = _prevState = _init; }
		~stateobj () {}
		...
		...
		...
		state run () { _prevState = _curState; _curState = _proc[_curState](); return _prevState; }
	private:
		state _curState;
		state _prevState;
		state error ();
		state init ();
		state wait ();
		state shutdown ();
		static state (stateobj::*_proc[_numStates])();
	};

// Within .cpp file...
stateobj::state (stateobj::*stateobj::_proc[stateobj::_numStates])() =
	{
	stateobj::error,
	stateobj::init,
	stateobj::wait,
	stateobj::shutdown
	};

Advertisement
Lets take a step back and look at your design. I'm assuming that what you want to do is roughly in the function pointer, correct? Your original problem was that you wanted to get away from a "list of function pointers" approach to a more OOP way, also correct? In that case, it might be best to ditch the function pointers intirely. In C++, you might do it this way:

First have a base "interface" class called "State". Then derive from State and implement any state-specific jiggers in the subclasses. For instance, here is the theoretical State base class:

class State {   public:      virtual void DoStuph() = 0; // this means "pure virtual", i.e. can't create a "State" class by itself      ~State();   protected:      State();   };


Now for each of the actual states you want in your project, you create a derived class like so:

class StateTitleScreen: public State {   public:      virtual void DoStuph() {         /* do state-specific stuph here */         }      ~StateTitleScreen();      StateTitleScreen();   private:      /* state-specific vars here */   }


So in the main game loop, you basically end up with this:

State* current_state = new StateTitleScreen(); // first screen player seeswhile (gameloop) {   current_state->DoStuph();   }


If the player changes the state through some mechanism, you would do something like this:

delete current_state; // out with the oldcurrent_state = new StateWhateverElseYouWant(); // in with the new


This way, the gameloop doesn't much care what the current state is, as long as it has the DoStuph() interface.

Hope that helps a bit. Feel free to ask questions. And i appologize if i totally misjudged the problem.
The problem is that function pointers to member functions require an object as well, this should do the trick ...

using ->* operator:
_curState = this->*_proc[_curState]();

using .* operator
_curState = (*this).*_proc[_curState]();

I hope that is right :O function pointers to member functions are scary.

EDIT: This is assuming of course that the function pointed to by _proc[_curState] should act on the object making that call, hence the "this" pointer.
leiavoia - You have correctly judged what I'm trying to do. I see where you're going with this OOP approach and generally like the concept, thank you.

I have one concern though. In the old way of doing things, switching to a new state required minimal processing: simply change the data variable that indexes the array of function pointers (e.g. "prevState = curState; curState = newState;"). In your approach, I would have to deallocate the old state instance and and allocate a new state instance to accomplish the same. Would this not be a bit more costly in terms of performance?

EDIT: Perhaps I can aloc all game states during program init, then use a base object pointer to simply point to the current state... something like the following:

StateTitleScreen TitleScreen; StateOtherState OtherState; ... // alloc and init all states at program startup...State *curState = TitleScreen; // set initial state...curState = OtherState; // switch to new state


[Edited by - BrianMJC on April 28, 2006 10:13:15 PM]
AsOne - Nice try, but I still get the same error. I'm not sure if that's the problem since the array of function pointers is static? Yes, they are very scary. :)
try this,
_curState = (this->*_proc[_curState])();
if that doesn't work then I'm out of ideas :S
AsOne - Hey, it compiled! I'll test it now...

EDIT: Thanks, it works perfectly. :)
Thanks both of you - I now have a working program, plus a neat idea for a more OOP implementation.
Quote:I have one concern though. In the old way of doing things, switching to a new state required minimal processing: simply change the data variable that indexes the array of function pointers (e.g. "prevState = curState; curState = newState;"). In your approach, I would have to deallocate the old state instance and and allocate a new state instance to accomplish the same. Would this not be a bit more costly in terms of performance?

EDIT: Perhaps I can aloc all game states during program init, then use a base object pointer to simply point to the current state... something like the following:


Wow, you really are a C programmer! The answer is: no, it would not hurt performance. If you want to work with C++ it is best not to think on this level of performance (that is, bit-shifting hax0rz extratrickery). On modern machines, these kinds of micro-optimizations mean nothing. To illustrate: I built a particle system that animated thousands of particles every frame. In order to produce the particles, i could either create a list of them ahead of time in a "dead" or "live" state and "recycle" the dead ones when i needed to create a new one, OR i could just allocate and deallocate them as needed. In rigorous testing, i determined that it made absolutely no difference on the frame rate either way.

So don't worry about it :-)

If on the other hand, changing state requires a lot of activity (dumping and loading textures, creating a new world/environment, and other high-CPU things), then you might consider doing that, but you would then be eating up a lot of memory, i'm sure.
leiavoia - Very good, thanks. Yes, years ago I professionally programmed in assembly language (on Intel 80386/486 PCs, plus on some microcontrollers) and later in C. I've come to terms with using 32 bit boolean values (instead of making every bit count with logical operators), but treating memory allocations & deallocations as similar in performance to a couple of simple data assignments will take some getting used to! :)

This topic is closed to new replies.

Advertisement