Polymorphism and arithmetic of pointers do not mix, since the location of objects inside the array depends on the derived size itself, and polymorphism loses this information. Dynamic allocation is a red herring, you can see the same problem:
Derived array[2]; Base* p = array; printf("%p\n", &array[0]); printf("%p\n", p); printf("%p\n", &array[1]); printf("%p\n", p + 1); printf("%z\n", sizeof (array[0])); printf("%z\n", sizeof (*p));
Note that the pointer values ββare moved forward by sizeof (Derived) using array , but pointer arithmetic using p moves forward sizeof (Base) and cannot find real objects.
You usually fix this with a Base* array instead of a single Base* in combination with pointer arithmetic.
Base* pp[2]; for( auto& elem : array ) pp[&elem - array] = &elem; printf("%p\n", &array[1]); printf("%p\n", pp[1]);
Another option is to use an object that remembers the original type:
Derived* allocated = new Derived[N]; std::function<Base& (int)> poly = [allocated](int i){ return allocated[i]; };
and use poly(i) instead of p[i]
But a warning, you CANNOT do delete [] &poly(0); , because delete[] also not polymorphic.
Using std::unique_ptr<Derived[]> and std::bind , you can arrange for automatic release when the accessory object finally goes out of scope.
source share