• Advertisement

Archived

This topic is now archived and is closed to further replies.

"backward" access in a class

This topic is 5900 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

My problem is that i want to have access "backwards" in a class..
      
class Combat {
void Exit();
};

void Combat::Exit() {
menu = 3; <----- tryning to get access to
blah = 4; <----- game.xxxx (ex. game.menu)
test = 5; <----- problem, no scope/access
}

class Game {
int menu;
int blah;
int test;
Combat combat;
};

int someFunc() {
Game game;
game.combat.Exit();
}
      
Is there any way/operator to get access to Game´s membs, throught Combat´s functions, (without sending them in as reference in a parameter?) Is the sollution to use friend/protected classes? (i don´t really understand the meaning/use of friend classes/protected membs) //jimmy /edit (spelling) Edited by - PopJimmy on February 25, 2002 4:14:59 PM

Share this post


Link to post
Share on other sites
Advertisement
This should work:


        
Within a Combat function, e.g.:

void Combat::Exit()
{
Game * pParent = ((Game*)((unsigned char*)this - offsetof(Game, combat)));

// access Game as you like...

pParent->Blabla();
...
}


(look at offsetof() in the MSDN). BTW: the MFC provide exactly this funcionality with the macro METHO_PROLOGUE. That's where I got the solution from.

Bye, VizOne


Edited by - VizOne on February 25, 2002 6:32:59 PM

Share this post


Link to post
Share on other sites
That is one of the worst abuses of the language that I have ever seen. Goto is a shining beacon of purity by comparison.

Pass parameters. Or merge the classes. Or have one class contain both of them and let it have the responsibility for synchronising them. Please, please, don''t do the stuff in the above post...

[ MSVC Fixes | STL | SDL | Game AI | Sockets | C++ Faq Lite | Boost ]

Share this post


Link to post
Share on other sites
You need to design your classes so that they have accessible semantics from other parts of your program. It is not desirable that one class have direct access to the implementation of another class, since that couples the classes very tightly together. A change in the implementation of one class will possibly break the other class - bad encapsulation.

If you have a class called Game, and you want another class to be able to modify Game''s behaviour, then you should consider adding functions into the interface to enable changes to Game''s behaviour. In general, you should think at a higher level of abstraction than adding simple accessor and mutator functions, which is a very naive view of encapsulation:

  
class Game
{
public:
int getTest() const { return test_;}
void setTest( int test ) { test_=test;}
//... other accessors and mutators ...

private:
int menu_;
int blah_;
int test_;
};


If you do something like the above, you have achieved the aim of making the private variable test_ accessible to the outside world, but encapsulation is bad. Other parts of your program will become dependent on the internal implementation of your class having a variable called test_ of type int, and will expect certain things to result from changing test_. You might aswell make the variables public (and no, that''s not a recommendation).

It would be better to think of the likely high-level functions that can be applied to a game which don''t expose the class internals. Things like "start game", "quit game", "game over" spring to mind.

I don''t know why you have a variable called "menu" in your game class, and I don''t know why you want a class called "Combat" to affect the menu variable. I would guess that, if your design does look like this, you need to rethink your class decomposition schema.

Note that the "friend" concept also suffers from the same problems of direct accessors / mutators (although, admittedly, it''s more restrictive). Sure, it will give you access to another class''s internal representation, but that is a bad idea. As for VizOne''s suggestion, I have to agree with Kylotan. It''s an abomination. Not only does it suffer all the same problems inherent in exposing class internals, it makes huge platform dependent assumptions, bypasses the type-safety system and looks like it relies on undefined behaviour.


--

It is against the law to stare at the mayor of Paris.

Share this post


Link to post
Share on other sites
This is a trickey problem I had to fix. I just put the 'base class' into a global variable and use a pointer tree to access any class I want

You could also have a void* that points to the creating class of each of your classes (doesnt make sense!)

you have to use a void* because the first class hasn't been defined yet, it gets included AFTER the first!!! that only applies to the H file though. you could even pass the 'this' pointer in the constructor to make it a private variable

try this (psudocode!)

class2
{
void *lpParent
}

class1
{
Class1(); //Constructor

int iWhatever;

Class2 *lpSecondClass;
}

Class1:Class1() //--- Constructor
{
lpSecondClass = new SecondClass();
lpSecondClass->lpParent = (void*)this;
}


Class2:Whatever()
{
((Class1*)lpParent)->iWhatever = 1; //Messes with a lower class
}

Edited by - Cybertron on February 26, 2002 12:55:13 PM

Share this post


Link to post
Share on other sites
Use forward declarations instead of those void* and casts.

Im not saying it would be proper design but if it is..


//untested read as pseudo

class Class1;//Class2 need to know there is a Class1

class Class2
{
public:
Class2(Class1 *_Parent):
m_Parent(_Parent)
{}
//define functions using class1 here
//implementation goes into a implementationfile
//.cpp/.cc .whatever) that includes both class defenitions.

private:
Class1 *m_Parent;

};

class Class1
{
public:
Class1()
{
m_pClass2 = new Class2;
}

void someFunc()
{
//use class2 here
}

private:
Class2 *m_pClass2;
};


but as (SabreMan) pointed out eariler, this gives you very tight coupling between the classes so the design is probably flawed.
But using forward declarations is WAY better than casting void*.
Always use forward declarations if a new class need to know about a class not yet defined. (go look it up in your favorite C++ book or google it)

Share this post


Link to post
Share on other sites
the basic idea of the whole design thing idea was to have a heiarchy with a base class called Game.
(here is a fast-downcutted-version):

  
class Game
{
void Run();

Gfx GfxObj; //obj that holds all the gfx stuff

Sound SoundObj; //obj that holds all the sound stuff


Intro Intro; //class that just represents a game mode

End End; //class representing a game mode

int game_menu;
};

void Game::Run()
{
while (game_menu != GM_END) {
switch(game_menu) {
case (GM_INTRO): Intro.Run(); break;
case (GM_COMBAT): Combat.Run(); break;
}
}
}

void Intro::Run()
{
Game.Gfx.some_var = 3; <--- here my problem comes...
}


i don´t know... is this whole design idea a good approach?

anyone got any suggestions?

Share this post


Link to post
Share on other sites

  • Advertisement