Some practical reasons are:
- Compile time (changing private members no longer causes a recompile in all dependent source files)
- Hiding private members from public declarations (less "noise" in the public class declaration)
- Binary compatibility (even if you add variables to the impl object, the size of the pointer won't change, so you won't break binary compatibility)