Polymorphism & Pointers to arrays [duplicate]

I have a class A:

class A
{
    public:
        virtual double getValue() = 0;
}

And a class B:

class B : public A
{
    public:
        virtual double getValue() { return 0.0; }
}

And then in main() I do:

A * var;
var = new B[100];
std::cout << var[0].getValue(); //This works fine
std::cout << var[1].getValue(); //This, or any other index besides 0, causes the program to quit

If instead I do:

B * var;
var = new B[100];
std::cout << var[0].getValue(); //This works fine
std::cout << var[1].getValue(); //Everything else works fine too

Everything compiles fine, but it seems as though there is something wrong with my polymorphism perhaps? I'm puzzled.


Solution 1:

You can't treat arrays polymorphically, so while new B[100] creates an array of B objects and returns a pointer to the array - or equivalently the first element of the array - and while it is valid to assign this pointer to a pointer to a base class, it is not valid to treat this as a pointer into an array of A objects.

The principal reason that you can't is that (typically) derived objects are a different size to their base classes, so attempting to access the array as an array of base class objects will not use the correct offset to get a pointer to the next base class subobject of the next member of the derived class array.

Solution 2:

There is no problem with the polymrphism but with the way you are dealing with memory. The [] operator will advance you through the array by the sizeof(A) bytes in the first case and the sizeof(B) bytes in the second case. Because the objects are of type B the A* is not pointing to the correct location in memory.

Here is another way of looking at it

char * var;
var = (char*) new B[100];
std::cout << ((A*)var[0]).getValue(); //This works fine
std::cout << ((A*)var[1]).getValue(); //This will fail
std::cout << ((A*)var[sizeof(B)]).getValue(); // should work