#include <cassert>
struct base
{
base() {}
int nvalues = 0;
double *values = nullptr;
};
struct derived : base
{
derived() : base() {}
bool flag = true; // just to add another field
};
double checksum(base *array, int m)
{
double sum = 0.0;
for (int i = 0; i < m; ++i)
for (int j = 0; j < array[i].nvalues; ++j)
sum += array[i].values[j];
return sum;
}
#define N 5
#define M 5
int main()
{
derived *d = new derived[M];
for (int i = 0; i < M; ++i)
{
d[i].nvalues = N;
d[i].values = newdouble[N];
for (int j = 0; j < d[i].nvalues; ++j)
d[i].values[j] = 1.0;
}
double sum = checksum(d, M);
assert(sum == N*M);
return 0;
}
I think I got the reason why it doesn't work and why, if I remove theflag field, it runs smoothly. Still I wonder why if I swap the order of the fields in the base struct everything goes fine and (even more) how cases like this should be implemented to have just one checksum function...
checksum is expecting a pointer to base. You are passing a pointer to derived. One element of base is not the same size as one element of derived (base is not same size as derived). Hence the memory indexing is incorrect - hence the program breaks. It worked when you removed flag as in that case the size of base is the same size as derived so the indexing works. But that would be fragile code.
That s exactly what I guessed! I decided to go for generic programming and use:
1 2 3 4 5 6 7 8
template <typename T> double checksum(T *array, int m)
{
double sum = 0.0;
for (int i = 0; i < m; ++i)
for (int j = 0; j < array[i].nvalues; ++j)
sum += array[i].values[j];
return sum;
}