problem accessing base-class array

Hi! I have a program like the following one where the function checksum should be able to run on different classes derived by base.

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
#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 = new double[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...
Last edited on
1
2
derived *d = new derived[m];
void checksum(const base *array, int m);


The d[k] has some address.
The address of d[k+1] is sizeof(derived) bytes after d[k].

The array[k] has some address.
The address of array[k+1] is sizeof(base) bytes after array[k].

sizeof(derived) != sizeof(base)
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;
}
Topic archived. No new replies allowed.