Passing a Class...

Hi, I'm new here, so sorry if this is a stupid question or something.

In my game, I have a Stage Manager class, which basically controls which "stage" the user is in right now. (EG: The menu, or the game)

Each stage is a class derived from a stage called stg_basic.

The stage is changed by using StageManager::changeStage(stg_basic* newStage)

Here is a simplified version of changeStage:
1
2
3
4
5
6
7
bool StageManager::changeStage(stg_basic* newStage)
{
 //Create the new stage
 stage = newStage;
 stage->stage_start();
 return true;
}

I've tried multiple things to try and pass the new stage's class through the newStage argument, but nothing seems to work right.

However, with the above code I was able to get this to work:
1
2
stg_menu newmenu;
stageman.changeStage(&newmenu);

It's messy, but it works. However, I don't like having to create the stage using a variable then pass the variable. I've tried multiple things and can't seem to get something that works. (Some of it compilers, but I just get an exception.)

So basically:
Does anyone know how I can create a class, then pass it to my changeStage function without an extra variable?
OR
Does anyone know how I can specify a class to be created using changeStage?

Thank you for your time, sorry again if this should be obvious.

~DtD
Last edited on
In StageManager::changeStage() you assigning stage, which I'm guessing is a member of StageManager to point to an object local to a different function. Once this function (the one that called StageManager::changeStage()) returns, the object will go out of scope, so deferencing that pointer will cause a segmentation fault.

You should rewrite your method to this:
1
2
3
4
5
6
7
8
9
//I don't really see the point of returning anything, since there's
//no way the function could fail.
bool StageManager::changeStage()
{
 //Create the new stage
 stage = new stg_basic();
 stage->stage_start();
 return true;
}


http://www.cplusplus.com/doc/tutorial/dynamic.html
Last edited on
The poroblem is that I want to pass anothe class that is derived from stg_basic, like stg_menu or stg_maingame for instance. Your code will only work for stg_basic.

Also, changeStage will eventually also clean up after the last stage, etc. That's why it returns a value.

-------------

So I have stg_basic, it is just an emptry stage that does nothing:
1
2
3
4
5
6
7
8
9
10
11
12
13
//From StageManager.h
class stg_basic
{
 public:
  virtual bool stage_start();
  virtual bool stage_run();
  bool drop();//End the scene and deletes it.
};
//----------------------
//From SceneManager.cpp
bool stg_basic::stage_start() {return true;}
bool stg_basic::stage_run() {return true;}
bool stg_basic::drop() {delete this;return true;}


Then here is an actual stage, a basic menu for the game:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//From stg_menu.h
class stg_menu : public stg_basic
{
 bool stage_start();
 bool stage_run();
};

//From stg_menu.cpp
bool stg_menu::stage_start()
{
 echo("stg_menu Started!");
 gui::IGUIStaticText* myFunText=guienv->addStaticText(
   L"Welcome to DtD Tower Defense\nPress 'S' to START\nPress 'ESC' to EXIT",core::rect<s32>(10,10,620,440));
 myFunText->setOverrideFont(fnt_ocra);
 myFunText->setOverrideColor(video::SColor(127,255,255,0));
 return 1;
}
bool stg_menu::stage_run()
{
 if (input.key_check_released(irr::KEY_KEY_S))
 {
  echo("Player Pressed Start!\n");
  //stageman.changeStage(stg_game); //Or something
 }
 return 1;
}

So for example, on what is line 23 above, I want to tell the stage manager to switch to (a new instance of) the actual game's stage class when the player presses S.

---

I hope this clarifies things better...

~DtD
Last edited on
I would go with not actualy passing the class, just an Enumeration telling function what type of class it should create...

To helios, it might not be able to fail now, but he might be planning on adding things in the future which could cause it to ;)
In that case, you should leave the function unchanged, and instead call it like this:
stageman.changestage(new stg_menu());

Don't forget to delete this->stage before reassigning it or you'll create memory leaks.

EDIT: PseudoCode: It's possible to change the returning type of a function from void to anything else without maintainability problems. The opposite is not necessarily true.
Last edited on
@PseudoCode
I want to maintain the ability to add more stages as I feel later, so that doesn't work.

@helios
I've tried that, but I get a fun error from Microsoft Visual C++ Debug Libary (I'm using Microsoft Visual Studio 2008 Professional for this btw)
1
2
3
4
5
6
7
8
9
10
11
12
13
Debug Assertion Failed!

Program: t:\Development2\Dev\DtDTowerDefense2.exe
File: f:\dd\vctools\crt_bld\self_x86\crt\src dbgdel.cpp
Line 52

Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

For information on how your program can cause an assertation failure, see the Visual C++ documentation on asserts.

(Press Retry to debug the application)

[Abort] [Retry] [Ignore]


Yes, stg_basic->drop() deletes the old stage before the new one gets assigned =)

PS> I get this Warning while compiling:
warning LNK4075: ignoring '/EDITANDCONTINUE' due to '/INCREMENTAL:NO' specification
I don't know if that is any help. I tried disabling edit and continue tp see of that fixed it, but it didn't.

~DtD
Last edited on
You are probably deleting an invalid pointer.
Initialize the pointer you're trying to delete to 0 (or to something else), and before trying to delete it, see if it's zero. If not, then it's safe to be deleted.
You're right, I was deleting an invalid pointer, but I'm confused as to why changing the way I created the class activated that error. Ah well, not much of a concern to me, atleast I found it...

However, I now get a bunch of exceptions now from my game's camera code (not related in any way to the pointer)...and they go away if I comment out the stage manager stuff...even when using the same old variable method. Ah well, I probably tripped over a wire somewhere, I will try to figure this one out myself...

Ah, I found the problem with the excptions, it was because the garbage collection was killing off the camera controller's camera, oops!

Thank you both for your help!

~DtD
Last edited on
I don't know why not create stage objects by StageManager. The StageManager could be desgined as a container.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

class StageManager
{
public:
	template<typename Stage>
	Stage* create()
	{
		std::auto_ptr<Stage> ptr(new Stage);
		cont_.push_back(ptr.get());
		return ptr.release();
	}

	void destory(stg_basic* ptr)
	{
		std::vector<stg_basic*>::iterator it = std::find(cont_.begin(), cont_.end(), ptr);
		if(it != cont_.end())
		{
			cont_.erase(it);
			delete ptr;
		}
	}
	
	void changeStage()
	{
		std::for_each(cont_.begin(), cont_.end(), stage_change());
	}
private:
	struct stage_change
	{
		void operator()(stg_basic* ptr)
		{
			ptr->stage_start();
		}
	};
private:
	std::vector<stg_basic*> cont_;
};


Use it like this.

1
2
3
4
5
stg_menu* ptr_menu = stgmgr.create<stg_menu>();
stg_maingame * ptr_mg = stgmgr.create<stg_maingame>();

stgmgr.changeStage(); //The two object will be started
Topic archived. No new replies allowed.