#### Archived

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

# 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.

## 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 on other sites
Post this in the DP forum, and I''ll try to respond tomorrow (ZZZZZZZZzzzzzzzzzzzz................)

Magmai Kai Holmlor
- The disgruntled & disillusioned

##### 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 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 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 classclass Attack{private: Character &m_rCharacter; // reference to parent characterpublic: // 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 filevoid 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 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 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 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 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

1. 1
2. 2
3. 3
Rutin
18
4. 4
5. 5
JoeJ
13

• 14
• 10
• 23
• 9
• 49
• ### Forum Statistics

• Total Topics
632639
• Total Posts
3007588
• ### Who's Online (See full list)

There are no registered users currently online

×