The idea that I want to convey here is that the only time you need to look at
the dynamic type of a pointer/reference to an object is when you are invoking
a virtual function (or the destructors are virtual). And here we are not
dealing with any virtual functions, so we only need to look at static types of
pointers/references.

(1) int i = xptr->Xpublic; 
    This is clearly legal as xptr has static type of X* and X has a public
    data member Xpublic.

(2) int j = xptr->Ypublic; 
    This is not legal (even though xptr points to an object of type Y) because
    you dont have to look at the dymanic type of xptr (which is Y*), you just
    have to look at the static type (which is X*). And X does not have any
    data member Ypublic. So,this is not allowed.