Class Deriving Question

I'm a bit of a n00b when it comes to class deriving, so bear with me in this problem.

What if I want a class called sprite like this:
1
2
3
4
5
//Not necessarily perfect, I'm tired and can't test.  Please excuse syntax errors
class sprite{
public:
    void tick()=0;
};


Than, derived from sprite, I have many (50 plus) classes like:
1
2
3
4
5
6
7
8
9
10
11
class mover: public sprite{
public:
    void tick(){ /*Blah*/ };
    int number1;
};

class enemy: public sprite{
public:
    void tick(){ /*Blah*/ };
    int number2;
};


Now, this is all fine so far. The problem I'm facing involves a vector of "sprite"s.

 
vector<sprite> spriteVector;


Now, say that I have some "mover"s and some "enemy"s in the spriteVector. I could access their tick() by saying
 
spriteVector[i].tick();

but what if I need to access number1 or number2? Knowing if the variable exists in that certain class is not a problem in this case (scenario related) but I cannot access number1 / number2 without first defining them in sprite. Unfortunately, I feel that sprite would be flooded with values, causing all derived classes to have "junk" values they would never need, and use extra memory for no reason (in mass cases).

So, is it possible to access derived class variables that are not defined in the parent from a list based on the parent class?

Please explain in specific detail any answer please, I'm really lost (have been for a while)
That probably means you need an intermediate class betwseen sprite and mover,enemy,... that would be the only one to have that number, and make a vector of pointers to that type
That is if number1 and number2 have the same 'function'.
Last edited on
You can do it with pointers (yay pointers!)

Here is some example code. Note that the attempt to cast an enemy to a mover fails.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <vector>
#include <iostream>

using namespace std;

class sprite{
public:
    virtual void tick(){};
};

class mover: public sprite{
public:
    void tick(){ /*Blah*/ };
    int number1;
};

class enemy: public sprite{
public:
    void tick(){ /*Blah*/ };
    int number2;
};


int main()
{
  vector<sprite*> spriteVector;
  mover aMover;
  aMover.number1=3;
  enemy anEnemy;
  anEnemy.number2=18;
  
  spriteVector.push_back(&aMover);
  spriteVector.push_back(&anEnemy);
  
  std::cout << dynamic_cast <mover*> (spriteVector[0])->number1 << std::endl;
  std::cout << dynamic_cast <enemy*> (spriteVector[1])->number2 << std::endl;
  
  mover* testPointer = dynamic_cast<mover*> (spriteVector[1]);
  if (testPointer == 0) std::cout << "Dynamic cast of enemy to mover failed";
}
Last edited on
In response to the dynamic casting, what if we're talking about a lot of variables that would need to be dynamically casted? Like, too many to easily type?
A loop spring to mind.

1
2
3
4
for ( int i=0; i < spriteVector.size(); i++)
{
  // do something with spriteVector[i]
}
How would "mass" dynamically cast though?

Sorry, this is really kinda confusing me :D
I don't understand your question. What would you have to type too much? Are you asking how to do this:

1
2
mover* pointerToMover = dynamic_cast <mover*> (spriteVector[0]);
// now use pointerToMover to access the mover object 
Last edited on
But wouldn't that be effectively the same as just typing out each dynamic cast for each different variable in say, the mover class?

Like if mover had
int number1

to

int number 100

?
See my previous (modified) post. dynamically cast it to a pointer, and keep that pointer to use it again.
Alright, I'm starting to get you now (and more importantly, how this works!)

So, for every time of derived class I need to access would I have to have something like:

1
2
mover* pointerToMover = dynamic_cast <mover*> (spriteVector[0]);
enemy* pointerToEnemy = dynamic_cast <enemy*> (spriteVector[1]);


or is there a better solution? (many derived classes later, this could be a hassle)

In addition, to access say, 100 movers in the spriteVector, would I just change the dynamic cast pointerToMover to the correct location in the vector and use that? That sounds like it might be a bottle neck (just a hunch, never know)

Thanks for putting up with me, by the way!
Hate to do this, but bump. I need some more help.
or is there a better solution? (many derived classes later, this could be a hassle)

Like bartoli suggested, you could have an intermediate class between sprite and mover/enemy that contains the number (or use multiple inheritance), or you could add for instance an obtainNumber function to sprite.

e.g.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class sprite{
public:
    virtual void tick() = 0;
    virtual int obtainNumber() = 0;
};

class mover: public sprite{
public:
    void tick(){ /*Blah*/ }
    int obtainNumber(){ return number1; }
    int number1;
};

class enemy: public sprite{
public:
    void tick(){ /*Blah*/ }
    int obtainNumber(){ return number2; }
    int number2;
};
Last edited on
I don't know if this may help you, but you could try giving a identifier to each derived class, like:
1
2
3
4
5
6
7
8
9
10
11
12
enum ClassID{ ID_SPRITE = 0, ID_ENEMY, ID_MOVER.....}
class sprite {
    private:
        ClassID ThisID;
    public:
        sprite() { ThisID = ID_SPRITE; }
};
class enemy : public sprite {
    public:
        sprite() { ThisID = ID_ENEMY; }
};
// Also do for every class 


And cast at runtime based on the identifier?
I think the ID thing puts me in the same boat as I was in before. And the getNumber() idea is less than what I would like.

Each class may have TONS of variables exclusive to itself, and there may be tons of copies of each class in the spriteVector.

I don't know if that helps, but hopefully it might.
Or you could realize that the problem is your design (¿an enemy is a sprite? ¿"mover" is a sprite?)
And how you use your objects (too much coupling)
Well, the way layers are handled, I would consider movers and enemys sprites. They ALL have a tick() and paint() that is called every frame, but they may contain different specific variables.

For example:

Sprite and everything below has a tick() and paint()

Enemy has health to itself.

Mover doesn't need health, so it doesn't need the variable.

This would of course be on a larger scale in the actual situation.
It will be your design which needs tweaking. Only put health in the Enemy class and use that for a base class. So that anything which inherits from Enemy will have a health.
"favour composition over inheritance" Sprite would mean to fit better as an object contained inside enemy (enemy contains a sprite not is a sprite)

Accessing and mutational of number1 and number2 should only be done within the object's own tick class. (or maybe draw class)
Topic archived. No new replies allowed.