This is called slicing . When you push_back your elements to std::vector<A> , it basically copies elements to newly created instances of A Therefore, the part of the object that comes from the derived class will be lost ("cut").
To avoid slicing, you need to use a container that stores pointers instead of elements, so you should use std::vector<A*> <A *> or if your elements are a bunch, preferably selected by a vector of some kind of smartpointer ( std::shared_ptr or std::unique_ptr in C ++ 11, boost::shared_ptr or std::tr1::shared_ptr otherwise).
However, your code will not work as it is written, even if you change this: X , Y and Z all take their parameter by value, while all the elements in your vector will be of type A* , so dereferencing them will give A , therefore it will invoke the wrong method anyway. This could be solved by changing the signatures to always take A& or A* and use dynamic_cast to try to do this in type:
class X { void foo(A*) { std:: cout << "A"; } }; class Y : public X { void foo(A* p) { if ( dynamic_cast<B*>(p) ) std::cout << "B";
Of course, dynamic_cast is quite expensive, but if this is a problem, you might want to rethink your design. In addition, you need to ensure that A, B, C contain some virtual methods (a virtual destructor would be a good idea here), since otherwise dynamic_cast would not work)
source share