Archived

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

Challenger17

how does an object communicate with others?

Recommended Posts

wat''s the common way you guys take to do this? i just learned this:
// when i want to use A in B

class A
{
 ......
};

class B
{
......
private:
   A *ptrA;  // this is just a declaration

};
but i''m not sure about the detail, like where to instantiate class A, where to define the "ptrA"? what to do when there are a large amount of objects need to communicate? could u tell me a little more about this? thx!

Share this post


Link to post
Share on other sites
It Depends.

There are two real problems here:

- Making your object aware of the existence of the objects that it needs.

- Causing your object to use those other objects.

The first can be solved by caching pointers to them (or even full ''inner objects'', in C++ - in Java this kind of thing is weirder and kind of discouraged, because of the fact that objects are normally stored by reference), like you have in your example. You would typically set the pointer values by passing in A objects to the B constructor. If you need several such objects, just add in all the pointers you need - possibly grouped using arrays and/or (STL) container classes.

You can also solve it by always passing in the relevant A object as a parameter to B''s methods, where it is needed. You should think about what makes sense here.

If B is going to be a singleton anyway, there is an idiom that I use instead - some may frown on this, but at least in Java it seems quite natural. This is useful for the cases where B is basically an "AManager" class. Basically, you absorb class B into A, by implementing the B methods as static methods in A. Then have a static collection/array of A objects as a private member of A, as well. The static methods will generally iterate over the collection, performing (non-static) A methods on each A object in turn. E.g.

class A { // self-managing!

// other private stuff

static std::vector<A *> all_As;
public:
// other public stuff

public void drawSelf() {
// blah

}
static void drawAll() {
for (std::iterator i = all_As.begin(); i != allAs.end(); i++) {
(*i)->drawSelf(); // since I stored pointers, yeah?

// do some other logic stuff.

// or maybe you can make effective use of <algorithm> or other libraries

}
}
}


Of course, the second problem is pretty straightforward - just set things up such that your As present a visible interface to class B which includes the things that B needs.

Share this post


Link to post
Share on other sites
it seems i should strive to improve my programming ability, coz i can only understand a part of what u said

Thx a lot anyway!! u typed so much... it helps! really

Share this post


Link to post
Share on other sites
Ok, I started writing a little explanation of this but decided to scrap it as it was becoming confusing. Instead of using abstract class names like A and B I'm going to give you an example using two alternative classes named CPlayer and CGame respectively.

Lets say we have an instance of our CGame class and we'd like it to control an instance of our CPlayer class. First thing we do is ensure that CPlayer.h is included in CGame.h. This means our CGame class can read the CPlayer prototypes and understand how it works.

Then, just like you had in your A and B example we can ensure our CGame class has a pointer to a CPlayer object. It can be either private or public for now. This leaves our CGame header looking something like this...



#ifndef CGAME_H_
#define CGAME_H_


// include the CPlayer header file.

#include "Player.h"
// now this class knows how a player works and how to use one.



class CGame
{
public:
CGame();
virtual ~CGame();

// a pointer to a CPlayer object ready to be assigned

CPlayer *mPlayerPtr;

};


#endif


Got that? Right, with that in place we can create an instance of CPlayer somewhere in our CGame object (in the .cpp implementation) and then make sure our pointer points to it. Let's say we do it in the constructor, it would look something like this...


  
CGame::CGame()
{
mPlayerPtr = new CPlayer;
}


So what does that do? Well, as soon as our CGame object is created the constructor is called and that executes the code we just added. It creates a new instance of CPlayer in memory and then makes sure our pointer is pointing at it. This leaves you free to tell that CPlayer object what to do simply by calling it's functions with the arrow operator. So if CPlayer had a function called doStuff() we could simply have CGame call ...

 
// tell the player to do stuff

// could be something like animating, moving, jumping, farting...

mPlayerPtr->doStuff();


That would tell the CPlayer object what to do. Bare something in mind however, having created an object in memory at the start we need to make sure we remove it when everything is finished so you would be best off using the deconstructor to delete that CPlayer object like so...

 
// the deconstructor

CGame::~CGame()
{
// delete the player object we created at the start

delete mPlayerPtr;
}


Hope that is of some use and best of luck with it.



Edit: typo
Edit2: gah, what happened to my source tags!

[edited by - ghosted on March 31, 2004 3:51:25 AM]

Share this post


Link to post
Share on other sites
thank ya, ghosted! i completely got ya!

but, i have a question now: in your example, the CPlayer is under the control of CGame, this is alright, they two should have this logic. so, the communication is single-way --- message from CGame to CPlayer, no reverse(no necessary of course) so, what about when i have two objects need to communicates each other in a "double-way communication"?

Share this post


Link to post
Share on other sites
Ok, lets assume our CGame object has created 2 instances of CPlayer for some sort of multiplayer madness and (for whatever reason) you want the two of them to be able to communicate. We could achieve this link by letting the CGame object pass each one to the other and allowing it to direct a pointer at it.

So, we could start by adding a pointer to a CPlayer type inside the CPlayer class. In order to point that pointer at the other instance of CPlayer (the opponent) we''ll need some sort of function that CGame can use and then pass us the opponent. Something like this perhaps...



class CPlayer
{
public:
CPlayer();
virtual ~CPlayer();

// a function for registering the opponent class

void registerOpponent(CPlayer *opp);

// a pointer to our opponent

CPlayer *mOpponent;
};


So that actual function would be implemented in Player.cpp something like this...


void CPlayer::registerOpponent(CPlayer *opp)
{
// direct our mOpponent pointer to the Player object that gets passed to us

mOpponent = opp;
}


And finally to ensure those two instaces both get passed to each other we add the call to that function just after creating the players, perhaps in the CGame constructor...


CGame:CGame()
{
// create two instances of player

mPlayer1 = new CPlayer;
mPlayer2 = new CPlayer;

//let each one see the opponent and assign a pointer to them

mPlayer1->registerOpponent(mPlayer2);
mPlayer2->registerOpponent(mPlayer1);
}



So now the two CPlayer objects can communicate using the pointers they have to their opponent.

Share this post


Link to post
Share on other sites