Skip to main content

Section 16.4 Public and Private

Subsection 16.4.1 Using Public and Private

A class definition defines two things: the interface that is used to work with objects of that class and the implementation that describes how the work is actually done. The interface is the part of the class that is visible to the rest of the program while the implementation is hidden. A programmer who is working on some other part of the program should only have to worry about the interface of the class and not the implementation. This idea is referred to as information hiding.
The keywords private and public are known as access modifiers and are used to define what parts of a class are visible to code outside of that class. Using public: in a class says β€œeverything from here until the next access modifier is visible”. Using private: β€œeverything from here until the next access modifier is hidden”.
By default, all members of a class are private unless you place them in a public section, but it is good to explicitly indicate what you expect to be private. You can switch back and forth between public and private sections as many times as you like and put them in any order you like. Some programmers put the private portion first and the public section second. We will put the public section first as it is the part we wish to emphasize to anyone trying to understand the class.
It is a syntax error for code outside of a class to try to access members of that class that were defined in a private block:
Listing 16.4.1.
In this sample, the two member variables are named m_x and m_y. It is common convention (but not a syntax requirement) to decorate member variable names to clearly identify them. One convention is the one used here - to put a m_ in front of each name. Another convention is to use a single underscore after the name, like x_ or y_. The member variables are declared in a private block of the class and thus line 21 is a syntax error because it tries to access the private member from outside of the class.
To enable the rest of the program to access the information stored in the object, we need to provide a public interface that reveals the information. Functions that return a piece of data from an object are known as getters or accessors and usually have a name like getThing(). This sample adds getters for m_x and m_y:
Listing 16.4.2.
Now, the main function has a way to access the x coordinate of the point - via the public function that returns the private piece of data.
This public interface is a way for the class to control what other code can do to the object. Now other code can find out the value of m_x by asking the getX function for a copy of the value. But there is no way for outside code to get change the value of m_x because direct access is prevented. Other code can’t even access m_y at all as we have not provided a getter for that value.

Insight 16.4.1.

A good rule of thumb is that member variables should be private and member functions public. The functions are the interface and the variables are the implementation.
There will be rare exceptions:
  • A constant variable might reasonably be made public - there is no way for outside code to use it to change the state of the object.
  • There might be a function that is a useful helper to other member functions but makes no sense for outside code to use. That function could be marked private to prevent its use from outside the class.
But unless you have a very good reason, stick the the rule of thumb.

Checkpoint 16.4.2.

Which of the following are true?
  • By default, struct member variables are private.
  • By default, struct member variables are public. This is the main difference between a class and a struct.
  • By default, class member variables are private.
  • This is different from a struct, whose member variables default to be public.
  • Private member variables can be accessed within the class.
  • Private member variables are private to things outside of the class.
  • Public member variables can be accessed within the class.
  • Public member variables can be accessed anywhere, including within the class.

Subsection 16.4.2 Why use Private

This may seems like a lot of extra work. Instead of letting code access the member variables of a class directly, we instead write a function that code can call to get the value of that member. Most objects end up with many short getX() style functions that just do something as simple as return m_x;. So what is the advantage?
Because all outside access must pass through the public interface, the class has the ability to hide the details of the implementation. This is known as information hiding. Hidden information helps to enforce a wall between the code that should know all of the details of a given class (the code in the class) and code that should not depend on those details.
We say that code is tightly coupled when it depends on all of the details of other parts of the code. When code is tightly coupled, programmers need to know how all of those details work.
By forcing other code to use a public interface instead of the private details, we promote loosely coupled code. In loosely coupled code, a programmer does not need to know about all the details of some class they are using. If they are working with a Color object, they should not need to know how to make the color darker by manipluating its data. Instead, they should be able to just call a function like darken() and let the Color class handle the details of how to do that.
Furthermore, in loosely coupled code, it is much easier to change the implementation details without breaking other code. If other code is constantly checking m_x and m_y directly, we can’t change those variables without breaking that code.But if we force other code to use the public interface, we can change the implementation details as long as we preserve the interface.
For example, the programmer who is working on the Point class might decide they want to store the data for a Point in polar coordinates (as an angle and distance from 0,0 instead of an x, y pair). As long as they preserved the interface that assumed x and y coordinates, other code would not need to change. Note in this sample that main does not need to change at all even though Point is now storing its data in an entirely different way:
Listing 16.4.3.
Running this sample with the Codelens reveals what is going on. main asks for a point to be made with the coordinates 3, 4. The Point class translates this request into the data it will actually store, m_distance and m_angle. Later, when main asks for Point p1 to getX(), the Point class calculates the x location from what it has stored and returns that value.
The code isn’t handling some of the special cases for translating from x,y to polar coordinates correctly, but it still serves to illustrate the power of loose coupling. We can make significant changes to the Point class without affecting the main function because Point forces other code to use an interface that hides the implementation details.

Checkpoint 16.4.3.

What are some of the benefits of information hiding?
  • It keeps code secret from other programmers and users.
  • Incorrect! β€œhiding” is not a great term for what we are really doing. β€œprotecting” might be a better description.
  • It makes it easier to change implementation details of a class without breaking code that uses the class.
  • It allows us to enforce boundaries between code that β€œknows the details” of a particular type and code that does not know or depend on those details.
You have attempted of activities on this page.