a = b;
Musisz wiedzieć, że referencje (zmienne referencyjne) też podlegają zasadom polimorfizmu. Dlatego operator= (przypisania) (przyjmujący referencje na A) przyjmie też referencje na B. Jednak przypisanie b = a już nie było by możliwe. Podobnie jak B* bptr = &a; też by nie przeszło. Teraz a.a jest równe b.a (b.b zostało pominięte bo obiekt a nawet nie wiedział, że zostaje mu przypisany obiekt klasy B - w końcu dostał referencje na A (A&)).
pa = pb;
Wiadomo, polimorfizm dla wskaźników... Od teraz pa i pb wskazują na ten samo obiekt - b.
a.f() wywoła metode A::f() - wiadomo. Ale skoro został mu przpisany obiekt b, to a.a jest teraz równe 4. Wiec a.f() zwróci 5.
a.g() - podobnie. Zwróci 2.
Obiekt b został nietknięty, więc b.f() zwraca 4 + 2 i b.g() zwraca 4 - 2.
pa->f() Co prawda metoda f() jest wywoływana z pod wskaźnika na A, ale f() jest wirtualna i została przeciązona w klasie B, więc zostaje wywołana metoda B::f()
pa->g() Metoda g() wirtualna już nie jest, więc skoro zostałe wywołana z pod wskaźnika na A, to wywołana zostaje metoda A::g()
pb->f() Tutaj już bez wątpliwości wywołana zostaje B::f()
pb->g() Podobnie tutaj zostaje wywołana B::g()
Mam nadzieje, że pomogłem :)