2

Can someone tell me and provide a code example of whether it is possible to create an array that can hold any types of objects without using inheritance in c++? I haven't written any code for it yet, but for example if I have 2 classes: RangedWeap and MeleeWeap, is there a way to store these objects in the same array without using inheritance?

Danny
  • 9,199
  • 16
  • 53
  • 75
  • Any particular reason why you don't want to use inheritance? – Kevin Jul 17 '12 at 17:54
  • 2
    Use a proper inheritance model and save yourself the headache of working with `void*`'s. – Ed S. Jul 17 '12 at 17:55
  • been told inheritance is slow for game engines – Danny Jul 17 '12 at 17:55
  • 3
    Virtual inheritance *can* slow things down if you're making a ton of virtual function calls in a tight loop or something similar. However, remember that optimization like this is really for experts only. It takes a lot of experience to know what will be slow before running any tests to verify that your *assumptions* are correct. And even then, we test. – Ed S. Jul 17 '12 at 17:56
  • 6
    Avoiding inheritance out of principle as a means of optimization without first profiling and benchmarking has been the root of all evil for 30 years. ;) Code for clarity and maintainability. When a performance issue is detected, profile, find a better algorithm, and finally as a last resort, start trimming cycles in the narrowest possible portion of the code, at the expense of maintainability and clarity. – DavidO Jul 17 '12 at 17:56
  • @EdS. Now that you've mentioned void*, is that the same as using HANDLE ?? – Danny Jul 17 '12 at 17:56
  • Didn't [boost::any](http://www.boost.org/doc/libs/1_50_0/doc/html/any.html) offer better error checking than the void* approach? It's another library, but if you are already using boost anyways ... –  Jul 17 '12 at 17:57
  • 2
    No, it's the same as using `void*` :D Handle is an opaque type, yes. However, I will reiterate; you are making a mistake. How about setting up a test case per your usage scenario and seeing what the performance difference actually amounts to? I will say that, in a tight loop iterating over a large data set you should be making as few function calls as possible anyway, virtual or not. But again, don't assume! Test. – Ed S. Jul 17 '12 at 17:58

3 Answers3

7

If you want to store objects, no. The reason for this is that arrays store objects in contiguous memory, and the size of each stored object is identical. This doesn't necessarily hold for different types.

There's an ugly way of doing it storing void*, but that would be storing pointers, not objects. Also, it would be useless, as all type information is lost. How in the world could you determine what the void* points to (assuming you don't have a base class)?

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
2

Boost.Any will enable this, but it (probably?) uses inheritance under the hood, if you care.

Steve M
  • 8,246
  • 2
  • 25
  • 26
0

You will have a hard time distinguishing between the two objects, but given you have a way for that, you can use a union:

struct A
{
    int type;  // to distinguish
    ...
};

struct B
{
    int type;
    ...
};

union AB
{
    int type;
    A a;
    B b;
};

AB array[] = {<whatever>};

Later, you have to check for type when you access, to know whether you should access a or b in each element.

Note: your objects should be POD, unless you are using C++11 according to @chris.

Community
  • 1
  • 1
Shahbaz
  • 46,337
  • 19
  • 116
  • 182
  • Don't unions fail once you start having classes with constructors? –  Jul 17 '12 at 17:57
  • You can't have a non-POD type as union member, so this will only get you this far. It's a creative solution nonetheless. – Luchian Grigore Jul 17 '12 at 17:58
  • @LuchianGrigore, yeah, but this is as close as the OP can get with what he wants. I updated the answer. – Shahbaz Jul 17 '12 at 18:01
  • @Ethan, Looks like that restriction [got lifted in C++11](http://www2.research.att.com/~bs/C++0xFAQ.html#unions) – chris Jul 17 '12 at 18:01