Dynamic dispatch is only used when using pointers, not with class values:
Employee e1("Bob", 45000.00);
Manager m1("Alex", 60000.00);
// No dynamic dispatch here. Employee's getBonus is used
e1 = m1;
cout << e1.getBonus() << endl;
Employee *ep1 = new Employee("Bob", 45000.00);
Manager *mp1 = new Employee("Alex", 60000.00);
// Dynamic dispatch here since (a) pointers are used
// and (b) the getBonus function is 'virtual'.
// So Manager's getBonus is used since ep1 points to
// a Manager object
ep1 = mp1;
cout << ep1->getBonus() << endl;