I'll try to explain it on a lower level.
First of all, understand that a pointer is essentially simply a variable that holds a value, which happens to be an address in memory.
Let's simplify things and assume that every type has the same size and that there are only 5 addresses of memory (on the heap). (Also I will ignore that the array will allocate on the heap too.)
We now execute
Base* b = new D1();
Let's say that the allocated memory is at the address 3. b is now a variable that simply holds the value 3. Our (heap) memory looks like this:
0: ?
1: ?
2: ?
3: variable of type D1
4: ?
Then we continue with
v.push_back(b);
We now have that the array v holds one entry of value 3.
b = new D2();
We now allocated a new part of memory, let's say at address 1:
0: ?
1: variable of type D2
2: ?
3: variable of type D1
4: ?
b now stores this address, that is, the value of b is 1. If we look at v, we haven't changed it. It contains one entry with value 3.
v[0]->price();
This gives us a pointer with value 3, which we dereference and print. Given our memory map above, what is stored there is a variable of type D1.
Did this clarify things for you?
I also extended your code a little bit to demonstrate this with realistic addresses:
http://www.cpp.sh/3s4b4
(If you run that code, note that addresses allocated right after each other tend to be almost similar, often only differing by a single digit, thus look closely. For example, I got 0x1711260 and 0x1711220.)
If you really need to do what you expected, you could store a vector over Base** and store the address of b in the vector:
std::vector<Base**> v;
Base* b = new D1();
v.push_back(&b);
(*v[0])->price();
b = new D2();
(*v[0])->price();
Implemented on http://www.cpp.sh/8c3i3. But I wouldn't recommend that if you don't absolutely need to, lacks readability and unnecessarily confuses. (Note that the first pointer is not deleted in this example and unreachable after changing b, thus we'd leak memory.)