If everything in the public interface is a function, clients won't have to scratch their heads trying to remember whether to use parentheses when they want to access a member of the class. They'll just do it, because everything is a function.
Using functions gives you much more precise control over the accessibility of data members.
If you implement access to a data member through a function, you can later replace the data member with a computation, and nobody using your class will be any the wiser.
Hiding data members behind functional interfaces can offer all kinds of implementation flexibility. For example, it makes it easy to notify other objects when data members are read or written, to verify class invariants and function pre- and postconditions, to perform synchronization in threaded environments, etc.
The argument against protected data members is similar.
Suppose we have a public data member, and we eliminate it. How much code might be broken? All the client code that uses it, which is generally an unknowably large amount. Public data members are thus completely unencapsulated. But suppose we have a protected data member, and we eliminate it. How much code might be broken now? All the derived classes that use it, which is, again, typically an unknowably large amount of code. Protected data members are thus as unencapsulated as public ones, because in both cases, if the data members are changed, an unknowably large amount of client code is broken. This is unintuitive, but as experienced library implementers will tell you, it’s still true. Once you’ve declared a data member public or protected and clients have started using it, it’s very hard to change anything about that data member. Too much code has to be rewritten,retested, redocumented, or recompiled. From an encapsulation point of view, there are really only two access levels: private (which offers encapsulation) and everything else (which doesn't).
Things to Remember:
- Declare data members private. It gives clients syntactically uniform access to data, affords fine-grained access control, allows invariants to be enforced, and offers class authors implementation flexibility.
- protected is no more encapsulated than public.