The reason why we encapsulate data meaning making data members private to enforce access and update through member functions i.e. getters & setters are:
1. You determine that your type's represenstation is variable, meaning its data members can change over-time be it the name or the type of the memeber, if you did not encapsulate the variant then clients of your type will be tightly coupled to its representation thus if your type's represenstation changes then all clients are forced to update there code to reflect the changes and then recompile it all.
By
encapsulating the variant you make loose coupling by indirection, enforcing clients to access/update through an
invariant interface i.e. member functions.
2. You determine that your type has a
state invariant meaning that the representation has
range of valid values but clients are allowed to update the representation so to enforce the state invariant you make the representation private and enforce clients to use the interface i.e. member functions to update without putting the instance of that type in an
undefined state. If the represenstation is public how could you ever maintain the
state invariant from clients? exactly you couldn't clients could easliy set invalid values into public data members.
So to summarize this:
encapsulate the variation/variant and provide invariant interface to it <-- important is the first key to abstraction
if your type has a state invariant then encapsulate it by making it private and enforce access/update through the interface i.e. member functions, there-for never putting an instance of that type in an undefined state.
If your type has none of these criteria then there is no reason to make it private, your type probably is not a real type and is nothing more than an aggregate/compound data structure.
A very good example of a type that does not encapsulate its data members and nor does it need to is the standard library type
std::pair, a pair has 2 members and this will never change it has no
state invariant to maintain there-for its members are public.
Also note if your type has lots of small
fine grained accessor methods i.e getters/setters then again you've modelled your type at the wrong or mixed the levels of abstraction and you've probably got nothing more than a an aggregate/compound data structure. If its mean't to really represent a proper type then perhaps your type's representation should be grouped into new types.