When an object is on the stack, you can really assign objects of the same type to each other. They can be converted via overloaded casting operators or overloaded assignment operators, but you specify the conversion at this point. The compiler cannot independently perform such conversions.
A a; B b; b = a;
In this case, you are trying to assign A to B, but A is not B, so it does not work.
A a; B b; a = b;
It works in fashion, but probably it will not be what you expect. You just chopped your B. B is A, so the assignment may take place, but because it is on the stack, it just assigns parts b that are part A. So what you get is A. not B, even though you assigned from B.
If you really want to assign objects of one type to another, they must be pointers.
A* pa = NULL; B* pb = new B; pa = pb;
It works. pa now points to pb, so it is still B. If you have virtual functions on A and B, they overlap them, then when you call them on pa, they will call version B (non-virtual will still call version A).
A* pa = new A; B* pb = pa;
This does not work. pa does not indicate B, so you cannot assign it to pb, which should point to B. Just because B is A, this does not mean that A is B.
A a; B* pb = &a;
This does not work for the same reason as the previous one. It so happened that A on the stack this time instead of a heap.
A* pa; B b; pa = &b;
It works. b is B, which is A, so A can point to it. Virtual functions will call version B, not virtual functions will call version A.
So basically, A * can point to B because B is A. B * cannot point to A because it is not B.