Accessing Members of Derived Objects

C6cb6c90c411f01492653729e7548a50
0
Flamesilver 101 Mar 25, 2011 at 16:06

I’m trying to code a game in C++. I’m having troubles implementing state objects while trying to follow this design framework (amazing article, btw):

[link]http://www.devmaster.net/articles/oo-game-design/[/link]

From my understanding, every GameEntity & GameForm has a std::map<string, State&> States. Every type of State (i.e. AccelerationRate or something) is a class derived from State, and therefore can be stored in this hashtable via its base pointer/reference (the State portion).

My issue is accessing those State objects. Since I’ll be storing a reference to the State base object and not its derived version, how do I access the derived object’s members through the base object reference?

Look at this pseudo-code example:

class BaseClass {
  public:
    int baseint;
};

class DerivedClass: BaseClass {
  public:
    int derivedint;
};

void main () {

DerivedClass dc;

BaseClass &BCP = dc;  // reference to the BaseClass portion of dc, which is derived

cout << BCP.derivedint;  // *** THIS DOESN'T WORK, DOES IT?! ***

}

3 Replies

Please log in or register to post a reply.

A8433b04cb41dd57113740b779f61acb
0
Reedbeta 168 Mar 25, 2011 at 17:23

Ahh, that’s a classic problem in OO design. One approach to solving it is to use virtual methods; if there’s a standard set of operations you need to perform on State objects, then you can make each one a virtual method, which has the same signature (parameters and return type) everywhere, but can have a different implementation (function body) in each derived class.

However, virtual methods are not very flexible. For full access to the derived class, you have to provide a way of figuring out what kind of derived class it is, and then cast the pointer to it. (I’ll describe this using pointers, but the same thing should be possible with references as they’re just syntactic sugar for pointers.)

One way of figuring out what kind of derived class it is would be to create an enum that lists all the possible derived classes and have a field for that in the parent class. Then you can switch based on that field and do the right thing.

enum ClassKind {
    ClassKind_Foo,
    ClassKind_Bar
};

class BaseClass {
public: ClassKind m_classkind;
};

class Foo: public BaseClass {
public: int m_fooInt;
    Foo () { m_classkind = ClassKind_Foo; }
};

class Bar: public BaseClass {
public: float m_barFloat;
    Bar () { m_classkind = ClassKind_Bar; }
};

void DoSomething (BaseClass * pBc) {
    switch (pBc->m_classkind) {
        case ClassKind_Foo: {
            Foo * pFoo = static_cast<Foo *>(pBc);
            // do something with pFoo; you can look at pFoo->m_fooInt, etc.
            break;
        }
        case ClassKind_Bar: {
            Bar * pBar = static_cast<Bar *>(pBc);
            // do something with pBar; you can look at pBar->m_barFloat, etc.
            break;
        }
    }
}
340bf64ac6abda6e40f7e860279823cb
0
_oisyn 101 Mar 25, 2011 at 17:39

Also, I would discourage the use of references in container types, as they’re not copy-assignable or default-constructable. For example, operator[] on your map will not work.

C6cb6c90c411f01492653729e7548a50
0
Flamesilver 101 Mar 25, 2011 at 20:32

Thanks for your help yet again!

I will use pointers, yes. That’s actually what’s in my code right now, anyway. Just figured references are cleaner to write and understand.

Seems like I keep running into these classic problems.