I have an interface which multiple classes inheritance.
class someInterface
{
virtual void someMethod() = 0;
}
class A : public someInterface
{
public:
void someMethod()
{
//Do something
}
}
class B : public someInterface
{
public:
void someMethod()
{
//Do something
}
}
class C : public someInterface
{
public:
void someMethod()
{
//Do something
}
}
For each of the classes A, B, C i have created an array with different sizes of their actual type inside a container class.
class AContainer
{
public:
A As[10];
}
class BContainer
{
public:
B Bs[5];
}
etc...
Furthermore i have an array of pointers to "SomeInterface", where i want to have a pointer to each of the actual arrays like this.
#define SOMEINTERRFACE_SIZE 3
someInterface *array[SOMEINTERRFACE_SIZE];
array[0] = AContainer.As; //Could also just be &AContainer.As[0]
array[1] = BContainer.Bs;
array[2] = CContainer.Cs;
for (int i = 0; i < SOMEINTERRFACE_SIZE; ++i)
{
int elements = //Here i need a solution to get the size
//So i can iterate through the array, which the pointer points to.
for (int i = 0; i < elements; ++i)
{
//Call the interface method on each element.
}
}
The problem occurs, when i have to use the someInterface array, since it isn't possible to get the size of the actual array through the someInterface pointer..
What is a good solution to this problem? I really need some help to solve this. Also don't want to use dynamic allocation, so no solution with vector<> or malloc etc. because I'm writing to an Arduino.
It won't work. In C++ you have to know the size of the elements in an array. A
, B
, and C
might be different sizes, so you can't treat arrays of them the same.
&AContainer.As[i] == &AContainer.As + i * sizeof(A)
but
&BContainer.Bs[i] == &BContainer.Bs + i * sizeof(B)
So it's impossible for the same machine code to iterate over arrays of A
and of B
. If you want to iterate over an array of objects, you need to know the exact type.
Remember in C++, if you want to get a polymorphic virtual call, you need to go through pointer or reference. The solution is to copy pointers to the elements in each array into one "master" array.
SomeInterface *ptrs[NUM_A + NUM_B + NUM_C];
SomeInterface **dest = ptrs;
for (int i = 0; i < NUM_A; ++i) {
*dest++ = &AContainer.As[i];
}
for (int i = 0; i < NUM_B; ++i) {
*dest++ = &BContainer.Bs[i];
}
// et cetera...
This only uses a little bit of extra space because you're storing pointers, not actual objects.
EDIT: I guess you could do something like this if you really want to save the space:
someInterface *arrays[] = { AContainer.As, BContainer.Bs, CContainer.Cs };
int objSizes[] = { sizeof(A), sizeof(B), sizeof(C) };
int arrLengths[] = { NUM_A, NUM_B, NUM_C };
for (int j = 0; j < sizeof(arrays)/sizeof(arrays[0]); ++j)
{
void *ptr = arrays[j];
for (int i = 0; i < arrLengths[j]; ++i) {
someInterface *iptr = (someInterface *)ptr;
iptr->method();
ptr += objSizes[j];
}
}
(this is untested, you might need to tweak a little.)
In theory since all those arrays are full of compile-time constants, it should optimize out to something fast. If it doesn't, the code will run slower because it will be incrementing pointers by a value only known at runtime instead of compile time. You should check the assembly output if you really care about speed.