Hey, all. I'm new here, and I hope to be able to contribute a lot.
I'm writing a game engine. It DOESN'T look like this. (But this is a pretty good bare bones representation of what's giving me grief.)
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 41 42 43 44 45 46 47 48 49 50
|
#include <iostream>
int main() {
/* A "thing" is an object that has coordinates, an update cycle,
a sequence of graphics, and a render cycle that renders the
current graphic at the coordinates. */
class thing {
public:
thing(int) {
std::cout << "Constructed thing" << std::endl;
}
};
class solid_thing: public virtual thing {
public:
solid_thing(int): thing(0) {
std::cout << "Constructed solid_thing" << std::endl;
}
};
class moving_thing: public virtual thing {
public:
moving_thing(int): thing(0) {
std::cout << "Constructed moving_thing" << std::endl;
}
};
class platform: public solid_thing, public moving_thing {
public:
platform(int): thing(0), solid_thing(0), moving_thing(0) {
std::cout << "Constructed platform" << std::endl;
}
};
class smooth_moving_thing: public moving_thing {
public:
smooth_moving_thing(int): thing(0), moving_thing(0) {
std::cout << "Constructed smooth_moving_thing" << std::endl;
}
};
class gravity_thing: public smooth_moving_thing {
public:
gravity_thing(int): smooth_moving_thing(0) {
// "error: no matching function for call to 'main()::thing::thing()'"
std::cout << "Constructed gravity_thing" << std::endl;
}
};
class platform_player: public gravity_thing {
public:
platform_player(int): gravity_thing(0) {
std::cout << "Constructed platform_player" << std::endl;
}
};
}
|
So, if I'm understanding multiple inheritance correctly, my tree should look like this.
1 2 3 4 5 6 7 8 9
|
t
/ \
st mt (nothing in this row constructs t)
\ / \
p st (everything in this row constructs t instead)
\
gt (so why does this row have to construct t too?)
\
pp (and is there any way around it?)
|
The reason I need solid_thing to be a class is because I have a template member function in my thing container class that looks kind of like this.
1 2 3 4 5 6
|
template <typename T> std::set<T*> collisions(thing* th) {
std::set<T*> retval;
/* populate retval with any things in this container
that are intersecting with th and inherit from T */
return retval;
}
|
So, if I wanted to check for collisions with solid objects, I'd call it with solid_thing as the template parameter. I could just change solidity to a boolean variable, and have an extra member function in my container class that only returns collisions with solid objects, but then every direct or indirect child of thing would have to be either solid or not solid, which may not be meaningful for some kinds of things (such as a message box).
As I hinted above, what I'm wondering is, if smooth_moving_thing, as a direct child of moving_thing which virtually inherits from thing, is already constructing an instance of thing, then why does gravity_thing, as a direct child of smooth_moving_thing,
also have to construct an instance of thing? And is there any way around it? I'm probably going to have a freaking million classes deriving directly or indirectly from moving_thing, and I don't want to have to manually construct an instance of thing for every single one of them.
One solution I've considered is making moving_thing, and any other direct child of thing other than solid_thing, a template class that derives from its parameter. That way, if I wanted a platform, I could just have it inherit from moving<solid_thing>, as opposed to multiply inheriting from moving_thing and solid_thing. I could have non-solid children of moving_thing inherit from moving<thing>. The thing is, that would mean I'd always have to treat moving<solid_thing>s as completely different from moving<thing>s, and I'm not sure whether or not that's desirable. Furthermore, deriving from the template parameter is something I've actually never tried before. Is this possible / feasible?
Thanks guys