Passing "this" pointer to member object

Started by
26 comments, last by rip-off 12 years, 10 months ago

[quote name='swilkewitz' timestamp='1306940984' post='4818293']
I am using the pointers to create a hierarchy of unrelated classes. The pointers would create a sort of "spine."

Game
>World
>Actor

A Game would hold an instance of World, and a World would hold a pointer of Game. So when Game is being constructed I want to create a World and set the World's pointer to the Game.

I thought that using the "this" pointer would work fine, but I wasn't able to get the "spine" working.
... gd.net reformatted puke elided ...

I know the first one is wrong, I never tried to do that. The second way is how I've been getting around the problem... though I've been passing &owner instead of owner.

So, what's the problem? That's fairly idiomatic.

World::World()
: game(this)
{ }

Game::Game(World* world)
: actor(world)
{ }

[/quote]

That is what I tried to do originally, but when I called higher-up functions using the pointers nothing happened. By using the workaround the pointers work, but I'd rather not use the workaround because that doesn't actually solve the problem.

Also, I'm getting memory problems now. I've been experimenting a lot....
When I start my game in debug mode everything is fine, but when I switch to release mode eveything goes haywire. I looked at taskmanager while running in release and I noticed the used memory cycling between 1.5 GB and 2.5 GB before crashing.

Unhandled exception at 0x768bb727 in Triax Bridge Command.exe: Microsoft C++ exception: std::bad_alloc at memory location 0x0035ed40..

I'm guessing I'm not being very careful with my pointers.
Advertisement

Unhandled exception at 0x768bb727 in Triax Bridge Command.exe: Microsoft C++ exception: std::bad_alloc at memory location 0x0035ed40..

I'm guessing I'm not being very careful with my pointers.

It appears that some state of yours is either really messed up (possibly due to scribbled-on memory), or you've accidentally tried to allocate a ridiculous amount of memory.

What does your debugger tell you?

[quote name='swilkewitz' timestamp='1306948961' post='4818348']
Unhandled exception at 0x768bb727 in Triax Bridge Command.exe: Microsoft C++ exception: std::bad_alloc at memory location 0x0035ed40..

I'm guessing I'm not being very careful with my pointers.

It appears that some state of yours is either really messed up (possibly due to scribbled-on memory), or you've accidentally tried to allocate a ridiculous amount of memory.

What does your debugger tell you?
[/quote]


I tracked through the creation of my objects and found these to be requiring too much memory:

Ship* s = new Ship();
s->addTexture(fileManager.loadTexture("ship1.bmp"));
s->addModel(fileManager.loadModel(s->scale, "ship1.model"));
space.addActor(s);

Asteroid* a = new Asteroid();
a->addTexture(fileManager.loadTexture("asteroid.bmp"));
a->addModel(fileManager.loadModel(a->scale, "asteroid.model"));
space.addActor(a);


The problem only comes up if I use both addTexture() and addModel() for only one of the objects.



Are you loading unique models/textures for each object, or are you cachine and sharing them somewhere?

Are you loading unique models/textures for each object, or are you cachine and sharing them somewhere?


So far they are unique (There are only two objects being loaded right now).

This solved the problem:

Ship* s = new Ship();
GLuint tempTex = fileManager.loadTexture("ship1.bmp");
s->addTexture(tempTex);

Model* tempModel = new Model(fileManager.loadModel(s->scale, "ship1.model"));
s->addModel(*tempModel);
space.addActor(s);

delete tempModel;


Should I stick with that solution or is that just dodging a worse problem?




What does fileManager.loadModel return? Does the Model class obey the "Rule of Three"?

You are probably just masking the problem, yes.

What does fileManager.loadModel return? Does the Model class obey the "Rule of Three"?

You are probably just masking the problem, yes.


I have heard of the rule of three before but never needed it. Now that I have read the wiki article about the rule I realize this is most likely the problem.

Also, I've been reading this faq
http://www.parashift.com/c++-faq-lite/
and I read something about handles being "ambiguous pointers." When it comes to the structure of my game, should I create a handle class so that I can change my method of object acquisition later on? I'm not sure I want to use pointers anymore because that faq recommends avoiding them, and they have been a pain so far.

What would you recommend for chaining the layers of my hierarchy?

When it comes to the structure of my game, should I create a handle class so that I can change my method of object acquisition later on?

IMO, strive to be simple and direct until you definitely know you'll need something a little fancier. Over-engineering is an all-too-common affliction.


I'm not sure I want to use pointers anymore because that faq recommends avoiding them, and they have been a pain so far.
[/quote]
I tend to avoid naked/raw pointers for anything except algorithmic or low-level work (e.g. image processing, a custom container, etc). For resource management, I'll always opt to create a smart pointer whose type describes the ownership semantics. Examples include boost::scoped_ptr and shared_ptr. If somebody hands you a shared_ptr, that says much more than being handed a raw pointer, for example.

If you have an aversion to boost, many modern C++ implementations come with similar classes as part of their standard library, in an std::tr1:: or stdext:: namespace or something similar. It's also a fun exercise to try to make such smart pointers for yourself, but it might be an idea to get them reviewed before relying on them too heavily :)
Ok, I replaced the plain pointers with auto pointers, though I don't know for sure if I am using them right. I'm pretty sure I am:

Ship* ship = new Ship();
auto_ptr<Actor> s(ship);
s->addTexture(fileManager.loadTexture("ship1.bmp"));
s->addModel(Model(fileManager.loadModel(s->scale, "ship1.model")));
space.addActor(s); //Space is a World


class World
{
public:
auto_ptr<Game> rootGame;
vector<auto_ptr<Actor>> actors;
}

World::World(auto_ptr<Game> g)
{
rootGame = g;
}

void World::addActor(auto_ptr<Actor> a)
{

a->rootWorld = this; //I haven't added the auto pointers everywhere yet, so Actor still uses the plain pointers
actors.push_back(a);
}

auto_ptr<Game> World::getGame()
{
return rootGame;
}

void World::act(GLfloat dt)
{

for(int i = 0; i < (int) actors.size(); i++){
actors->act(dt);
}

//for each(auto_ptr<Actor> a in actors){ //Is there a way to use for each loops with auto pointers?
//a->act(dt);
//}
}


The only problem I'm getting is that there is "[font="Consolas"][size="1"][font="Consolas"][size="1"]no copy constructor available or copy constructor is declared 'explicit'[/font][/font]" I'm guessing that is a prerequisite for using auto pointers... I'll work on adding that, and if I'm using auto pointers wrong please tell me.

Thank you all so much for all the help!
Scott
auto_ptr<>s have somewhat strange copy semantics. They're not "copyable enough" to be put in to containers such as std::vector, list and so on. So even if you do manage to get your code to compile, it likely won't be correct.

Something along the lines of boost::shared_ptr/std::shared_ptr/std::tr1::shared_ptr/stdext::shared_ptr is probably what you'd want, there.

This topic is closed to new replies.

Advertisement