What you need to understand is that there are two kinds of objects:
Objects that have behavior. These should refrain from giving public access to most/any of their data members. I expect only very few accessor methods defined for these.
An example would be a compiled regex: The object is created to provide a certain behavior (to match a string against a specific regex, and to report the (partial) matches), but how the compiled regex does its work is none of the user's business.
Most classes that I write are in this category.
Objects that are really just data. These should just declare all of their members public (or provide the full set of accessors for them).
An example would be a class
Point2D. There is absolutely no invariant that needs to be ensured for the members of this class, and users should be able to just access the data via
Personally, I don't use such classes much, but I guess there is no larger piece of code that I've written that doesn't use such a class somewhere.
Becoming proficient with object orientation includes realizing that this distinction exists, and learning to classify a class' function into one of these two categories.
If you code in C++, you can make this distinction explicit by using
class for the first category of objects, and
struct for the second. Of course, the two are equivalent, except that
class means that all members are private by default, while
struct declares all members public by default. Which is exactly the sort of information you want to communicate.