Jump to content
  • Advertisement

Archived

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

Pseudo_Code

OOP quesiton

This topic is 6400 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

I''m not sure if I''m quite approaching this question correctly, but here goes: Let''s say I''m working on a fighter. I have a character class, and an attack class.
class Character
{
public:
     Character();//constructor
     ~Character();//destructor
     ...
     ...
     ...//some other members/member functions

     Attack attackone;//character''s first attack
     
     ...
     ...

     int strength;//The character''s strength
}//class Character

class Attack
{
public:
     Attack();//constructor
     ~Attack();//destructor
     ...
     ...
     ...//insert crap here

     void perform();//Perform the attack
}//class Attack
 
For the sake of the question, we''ll say that Attack::perform() is dependant on its character''s strength. It needs to somehow use the value of "strength" from the character object that it exists in to determine the damage that will be inflicted. I have no idea how much sense the previous sentence makes. Anyway, how would I go about doing this?

Share this post


Link to post
Share on other sites
Advertisement
Post this in the DP forum, and I''ll try to respond tomorrow (ZZZZZZZZzzzzzzzzzzzz................)

Magmai Kai Holmlor
- The disgruntled & disillusioned

Share this post


Link to post
Share on other sites
There are a couple of ways to do this.


  1. The simplest way would be to pass the strength to the Attack::perform() . ie Attack::perform(int strength)
  2. If the strength is constant then construct the attack with a strength value.
  3. Before the attack set the strength ( sorta like #1 )


I am sure that there are a bunch more but those are just a couple off the top of my head.




-------
Andrew

Edited by - acraig on March 15, 2001 12:22:39 PM

Share this post


Link to post
Share on other sites
You could pass a reference to the character in the call to Attack:erform().

class Character{
public:
Character(); //constructor
~Character();//destructor
...
...
... //some other members / member functions
Attack attackone; //character''s first attack
...
...
int strength; //The character''s strength
}//class Character

class Attack
{
public:
Attack();//constructor
~Attack();//destructor
...
...
...//insert crap here
void perform(Character &character);//Perform the attack
}//class Attack

void Attack::perform(Character &character)
{
//perform character.attackone
character.strength = 100; //or whatever you wanna do with
//the character''s strength.
}

Share this post


Link to post
Share on other sites
OK, I typed out a really long response to this yesterday, but the forum was screwed and ate my post. I''ll give it another shot here.

One solution (not saying the best) is to have the attack know its parent character. I''ll show the code, then show how to implement it:
  
class Character; // forward declaration of class

class Attack
{
private:
Character &m_rCharacter; // reference to parent character

public:
// constructor

Attack (Character &parent) : m_rCharacter (parent) {/*..*/}
~Attack ();
void perform (); // perform attack
};

class Character
{
private:
Attack m_attackone; // attack "in size"
int m_strength;
public:
// constructor
Character () : m_attackone (*this) {/*..*/}
int getStrength () const { return m_strength; }
};

// cpp file
void Attack::perform ()
{
// get strength from parent (inline-supa-fast).
int strength = m_rCharacter.getStrength ();
/* ...do rest of function... */

}


OK, so there''s lots going on here. You''re creating a circular dependency between the two classes, which isn''t always a good thing, but might work for you.

You''re using an object of type Attack "in size" in the Character class. "In size" means you''re using an object, not a reference or pointer, so by the time the compiler gets to Character, it needs to know the exact size of Attack so it can incorporate it into the size of Character. This means that the Attack class _must_ be declared before the Character class.

However, the Attack class uses the Character class in its interface; since it''s just using a reference, you can get away with a forward declaration of Character (i.e. "class Character;") just before the declaration of Attack.

Attack has an internal reference to a character. Since this is a reference, its value must be set in the member initialization list of the Attack constructor. If you wanted to initialize it at some other time, you could change the reference to a pointer and do so.

Character, likewise, contains an Attack "in size"; since all constructors of members of a class are called before the class constructor is called, you must also initialize attackone in the member initialization list. Simple pass the dereferenced "this" pointer to attackone, and attackone''s constructor will store it as its m_rCharacter.

From now on, you''re free to use any of the public members of the Character object from within the Attack class. An example of how to do this is shown in Attack::perform ().

There are other ways to do this as other posters have shown. One is to pass the strength as a parameter, another is to pass a reference to Character each time. I prefer something like this method, but it does have the consequence of creating a circular dependency. Given more time, I believe I could construct a method that does not create that dependency, but I think it would require a third class (i.e. an "AttackManager").

So many ways to skin an OO cat.
(Hope the forum saves my reply this time)

Share this post


Link to post
Share on other sites
quote:
Original post by arsenius

AACCCCCCCCCHHHHHHHHHHhhhhh!!!!!!!!
OOP, keep it away! keep it away!!!

*arsenius runs behind a chair*

-arsenius
''after three days without programming, life becomes meaningless'' -The Tao of Programming



Your Tao of Programming has just enlightened me. Therefore, I will not have to test my programs anymore, because they''re perfect in themselves now.

But before you can realize Tao, you have to process the Evolution of a programmer!
http://www.ariel.com.au/jokes/The_Evolution_of_a_Programmer.html

Wunibald

Share this post


Link to post
Share on other sites
I would tend to recomment the first suggestion of passing a reference to your strength variable to Perform (ie, Attack::perform(int &strength).

The reason I choose this over circular dependancy is because I''d rather keep my classes as ignorant of each other as possible. The more classes are dependant on other classes, the less reusable your class is.


- Houdini

Share this post


Link to post
Share on other sites
quote:
Original post by Houdini

I would tend to recomment the first suggestion of passing a reference to your strength variable to Perform (ie, Attack::perform(int &strength).

The reason I choose this over circular dependancy is because I''d rather keep my classes as ignorant of each other as possible. The more classes are dependant on other classes, the less reusable your class is.



I agree with the reusability. But why would you want to pass a reference to an integer? Is Perform allowed to change strength? It seemed from the original post that it should not. Strength should be passed as an int, not as an int &.

Share this post


Link to post
Share on other sites
quote:
Original post by Stoffel

I agree with the reusability. But why would you want to pass a reference to an integer? Is Perform allowed to change strength? It seemed from the original post that it should not. Strength should be passed as an int, not as an int &.




It''s generally better to pass parameters by reference rather than value. The reasoning is that if you pass a large class to a function the function actually creates a seperate instance of the class and copies every variable from the original class into the new class. If you pass by reference then you are just passing a 4 byte memory address pointing to the original class, and no creating/copying of classes are involved.

Of course, passing an integer and passing a reference to an integer both passes 4 bytes, so in this case it TRUELY doesn''t matter. However, I always pass by reference both out of habit and to keep things uniform.

BTW, you are correct that the perform function I posted allowed the strength variable to be modified. It should have included a const:

Attack::perform(const int &strength);


- Houdini

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!