No slicing happens here, because you carefully pass objects by reference; slicing requires manipulating an object by value.
The effect is due to overload resolution, which is performed statically (i.e. at compile time). When C ++ compiles this member function
void A::bar(X &x) { x.foo(*this); }
he needs to decide, at compile time, which of the two overloads to choose. The solution is simple: the compiler knows that *this is of type A , so it calls the void foo(A &a) function.
You cannot make it work without implementing the same method in B * using templates or by implementing your own dispatch scheme with function objects or lambdas.
* and in this case, you will get an almost classic implementation of C ++ Visitor Pattern , a Double Sending implementation technique.
source share