Virtual inheritance, constructing the base class

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
Last edited on
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?

When you have a virtual base class, the most derived class is responsible for initializing it. The only way around it is to not use a virtual base class.
The most derived class? Even if a less derived class already initializes the virtual base class?

How does anyone get anything done with virtual base classes? Do they just suck it up and accept the fact that they're going to have to type lots of extra things that seem unnecessary? ... Actually, that seems like quite a C++ sort of solution.

You know what, forget it. I'll just use template classes that derive from their parameters. I'll have the base thing class store a set of type_infos, and have the class templates have specializations for void, and have each unspecialized variant store its corresponding void specialization to the set on initialization as an instance of type_info. That way, I'll be able to detect a thing as solid whether it's a solid<moving<thing> > or a moving<solid<thing> >.

Thanks for your help, cire.
Topic archived. No new replies allowed.