Jump to content
  • Advertisement
Sign in to follow this  
d000hg

Deriving from a class used for state-tracking?

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

Now it's common that in a class you may have an enumeration of possible states an object of that class can be in. But what about when you derive from this class, and a child needs an extra state? OO design says the parent shouldn't know about its children so putting every possible state in the base class is bad - but how can we achieve our aim in a 'good' way?

Share this post


Link to post
Share on other sites
Advertisement
hi,

I don't quite understand your problem :/


class CParent
{
public:
CParent();
~CParent();

virtual void SetStates(void);

protected:
int state1;
float state2;
};

class CChild : pulic CParent
{
public:
CChild();
~CChild();

virtual void SetStates(void); // set state3 and call the parent SetState method to set state1 and state2

protected:
char *state3;
};



Here, the CChild class will have visibility on state1 and state2, and add a third state. If you have a virtual class to set those states, you can store a list of CParent * and you don't have to care of visibility. The program will call the CChild::SetState if it needs.

Well, if this is not what you asked for, then sorry, I didn't understand then ^^

Share this post


Link to post
Share on other sites
Quote:
Original post by paic
I don't quite understand your problem :/


From what i understood he means something like:


struct foo {
enum bar {
CONSTANT1,
CONSTANT2,
CONSTANT3
};
// .....
};

struct foo2 : foo {
// now he wants to add a new member to the set of bar
// ....
};

Share this post


Link to post
Share on other sites
class CBase
{
public:
enum STATE {NONE,MOVING,WAITING,STOP};
virtual void ActOnState();
private:
STATE m_State;
};


Now let's say a child class wants a state called RUNNING, or TURNING, or SHOOT.
That's the problem. It's these enumerations which don't really work with derivation which are the problem.

EDIT: snk_kid beat me to the explanation of my own problem [smile]

Share this post


Link to post
Share on other sites
Quote:
Original post by d000hg
class CBase
{
public:
enum STATE {NONE,MOVING,WAITING,STOP};
virtual void ActOnState();
private:
STATE m_State;
};


Now let's say a child class wants a state called RUNNING, or TURNING, or SHOOT.
That's the problem. It's these enumerations which don't really work with derivation which are the problem.

EDIT: snk_kid beat me to the explanation of my own problem [smile]


This is a language limitation of C++, so you don't have a choice. You'll need to use an alternative, like the State Design Pattern. If this is merely an academic exercise for your own edification, you could try using Haskell, which does allow you to extend enumerations,

Share this post


Link to post
Share on other sites
It's a real-world problem. The state pattern seems a very complex way to fix what seems a simple problem, but I guess that's just the way it is. For applications where the original enumeration is not going to expand often or very much, presumably it's easier 9 times out of ten to just stick all the enumeration values needed by child classes into the base and live with the OO 'hack'?

Share this post


Link to post
Share on other sites
Why don't you use contants? After all, enumerations only define constants (and suffer the same problem than integer constants).

struct foo
{
static const int value1 = 0;
static const int value2 = 1;
static const int value3 = 2;
...
};
strut foo2 : public foo
{
static const int value4 = 3;
...
};

Of course, you have to give the value for every constant you create - it is not as simple as enumeration values. I see at least one "kind of" hack that will allow you to use a value without explicitely defining it. Something that look like this:

class UniqueValue
{
public:
operator int() { return (int)this; }
bool operator==(const UniqueValue& value) { return this == &value; }
};

// -- foo
#include "UniqueValue.h"
struct foo
{
static const UniqueValue enum_value_1;
static const UniqueValue enum_value_2;
static const UniqueValue enum_value_3;
};

// of course, in a cpp file:
const UniqueValue foo::enum_value_1;
const UniqueValue foo::enum_value_2;
const UniqueValue foo::enum_value_3;

// -- foo2
#include "foo.h"
struct foo2 : public foo
{
static const UniqueValue enum_value_4;
};

// and foo.cpp
const UniqueValue foo::enum_value_4;

This is of course far from complete, and I'm not even sure that it will compile. It works because each defined UniqueValue is static, and the address of 2 static objects can't be the same.
I guess there is a better way to do this (this way has some heavy problems) but I believe it should work.

Regards,

Share this post


Link to post
Share on other sites
Some interesting ideas there. Not sure if I can convince our lead programmer of the merits but it definitely looks like something I'll investigate for my own code, when I want states but without a whole FSM approach - for that I probably would follow the state pattern.

Share this post


Link to post
Share on other sites
Quote:


class UniqueValue
{
public:
operator int() { return (int)this; }
bool operator==(const UniqueValue& value) { return this == &value }
};




I think you forgot a *
operator int() { return (int)*this; }

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • 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!