Search

8.3 — Public vs private access specifiers

Public and private members

Consider the following struct:

In this program, we declare a DateStruct and then we directly access its members in order to initialize them. This works because all members of a struct are public members by default. Public members are members of a struct or class that can be accessed from outside of the struct or class. In this case, function main() is outside of the struct, but it can directly access members month, day, and year, because they are public.

On the other hand, consider the following almost-identical class:

If you were to compile this program, you would receive errors. This is because by default, all members of a class are private. Private members are members of a class that can only be accessed by other members of the class. Because main() is not a member of DateClass, it does not have access to date’s private members.

Access specifiers

Although class members are private by default, we can make them public by using the public keyword:

Because DateClass’s members are now public, they can be accessed directly by main().

The public keyword, along with the following colon, is called an access specifier. Access specifiers determine who has access to the members that follow the specifier. Each of the members “acquires” the access level of the previous access specifier (or, if none is provided, the default access specifier).

C++ provides 3 different access specifier keywords: public, private, and protected. Public and private are used to make the members that follow them public members or private members respectively. The third access specifier, protected, works much like private does. We will discuss the difference between the private and protected access specifier when we cover inheritance.

Mixing access specifiers

Classes can (and almost always do) use multiple access specifiers to set the access levels of each of its members. There is no limit to the number of access specifiers you can use in a class.

In general, member variables are usually made private, and member functions are usually made public. We’ll take a closer look at why in the next lesson.

Rule: Make member variables private, and member functions public, unless you have a good reason not to.

Let’s take a look at an example of a class that uses both private and public access:

This program prints:

10/14/2020

Note that although we can’t access date’s members variables m_month, m_day, and m_year directly from main (because they are private), we are able to access them indirectly through public member functions setDate() and print()!

The group of public members of a class are often referred to as a public interface. Because only public members can be accessed from outside of the class, the public interface defines how programs using the class will interface with the class. Note that main() is restricted to setting the date and printing the date. The class protects the member variables from being accessed or edited directly.

Some programmers prefer to list private members first, because the public members typically use the private ones, so it makes sense to define the private ones first. However, a good counterargument is that users of the class don’t care about the private members, so the public ones should come first. Either way is fine.

Access controls work on a per-class basis

Consider the following program:

One nuance of C++ that is often missed or misunderstood is that access control works on a per-class basis, not a per-object basis. This means that when a function has access to the private members of a class, it can access the private members of any object of that class type that it can see.

In the above example, copyFrom() is a member of DateClass, which gives it access to the private members of DateClass. This means copyFrom() can not only directly access the private members of the implicit object it is operating on (copy), it also means it has direct access to the private members of DateClass parameter d! If parameter d were some other type, this would not be the case.

This can be particularly useful when we need to copy members from one object of a class to another object of the same class. We’ll also see this topic show up again when we talk about overloading operator<< to print members of a class in the next chapter.

Structs vs classes revisited

Now that we’ve talked about access specifiers, we can talk about the actual differences between a class and a struct in C++. A class defaults its members to private. A struct defaults its members to public.

That’s it!

(Okay, to be pedantic, there’s one more minor difference -- structs inherit from other classes publicly and classes inherit privately. We’ll cover what this means in a future chapter, but this particular point is practically irrelevant since you should never rely on the defaults anyway).

Quiz time

1a) What is a public member?

Show Solution

1b) What is a private member?

Show Solution

1c) What is an access specifier?

Show Solution

1d) How many access specifiers are there, and what are they?

Show Solution

2a) Write a simple class named Point3d. The class should contain:
* Three private member variables of type double named m_x, m_y, and m_z;
* A public member function named setValues() that allows you to set values for m_x, m_y, and m_z.
* A public member function named print() that prints the Point in the following format: <m_x, m_y, m_z>

Make sure the following program executes correctly:

This should print:

<1, 2, 3>

Show Solution

2b) Add a function named isEqual() to your Point3d class. The following code should run correctly:

Show Solution

3) Now let’s try something a little more complex. Let’s write a class that implements a simple stack from scratch. Review lesson 7.9 -- The stack and the heap if you need a refresher on a what a stack is.

The class should be named Stack, and should contain:
* A private fixed array of integers of length 10.
* A private integer to keep track of the length of the stack.
* A public member function named reset() that sets the length to 0 and all of the element values to 0.
* A public member function named push() that pushes a value on the stack. push() should return false if the array is already full, and true otherwise.
* A public member function named pop() that pops a value off the stack and returns it. If there are no values on the stack, the code should exit via an assert.
* A public member function named print() that prints all the values in the stack.

Make sure the following program executes correctly:

This should print:

( )
( 5 3 8 )
( 5 3 )
( )

Show Solution

8.4 -- Access functions and encapsulation
Index
8.2 -- Classes and class members

170 comments to 8.3 — Public vs private access specifiers

  • Gizmo

    For my pop() function, instead of using an int function and returning a value, I used a void function and didn't return anything.

    Here is the example code:

    And here is my code:

    Note: The function takes place inside a class.

    1.)Why would you want to return an element that will not be used outside of the class functions?
    2.)Which method would be preferred here?

  • Jeff

    Style-wise, for clarity at the minimum, I personally prefer always having an explicit "private:" access qualifier even if the language (be it C++ or other) defaults to private.

  • Ngô Hoàng Đạt

    For quiz 2:

  • Kio

    For 3. my solution, sorry was using "using namespace std",

    • Hi Kio!

      * Initialize your variables with uniform initialization
      * Magic number: 10
      * Line 20: Indention
      * Line 24: @operator! is applied to @lengthOfTheArray, returning a bool, which you're then comparing to 0. You were probably looking for !=.
      * Line 27, 28: Can be merged into 1 line
      * Line 63: Unnecessary, as there is no input in your program.

  • btnal

    Hi,
    Can you answer me some questions ?
    1. Private access is only used for attributes, and public access is only used for methods, true or false. explain ?
    2. Make an example for a class that has the access method( function) is private.
    3. In general, why should not public access properties be public? Make an example.

    Thank a lot

    • Hi!

      1. false. There are lots of reasons to have private functions.
      2. Not sure what you're looking for

      3. Because you don't want the coder using the class to write arbitrary values to a member variable. By using a function you can filter out invalid values.

  • Hi

    Having some issues with the last one.  My code is thus:

    but it prints columns of 0's, not as would be expected.  Is my assert check wrong because it should throw a zero out?

    • Hi Nigel!

      @reset should reset @m_Index
      The assert in line 33 seems wrong, but the assert doesn't fire so I'll leave this up to you.
      @print is printing a line feed after every element.

    • John

      Hi

      In this code you are not actually resetting or removing the value in the stack(unless you print the values till m_index), so even if you print the stack it will show the value you pop(). Irrespective of how many times you do the pop().

  • and 2(b):

    I added the calls to print() in main() so that we could see what we were comparing.

  • 2(a):

  • Silviu

    Hello,
    How does m_next keeps track of all the counting, if it's not static, like s_maxStackLength ? (I mean it passes trough all the member functions like a static variable). It's like s_maxStackLength=m_next ? or ?

    • Alex

      The lifetime of a normal member variable is tied to the lifetime of the object that contains that it. Put another way, m_next will exist as long as the class object that contains it exists.

      At the top of main(), we define Stack stack. This contains a member m_next. stack.m_next will exist as long as stack does. And stack exists for pretty much the whole program -- thus so does m_next.

      • Silviu

        ok ok, so why the program "forces me" to create s_maxStackLength static.
        s_maxStackLength is const so it doesn't changes at all.

        I know in lesson 8.2, your giving an example similar with how it's m_next but i never thought it could remember the values.
        And yes you explain shortly "the implicit object" i hope i'm not wrong.

        • Alex

          > const int s_maxStackLength{ 10 }; // using without static

          This creates a s_maxStackLength member for each Stack object created. While that will still work, it means you are wasting 4 bytes per object holding a constant that doesn't change per object.

          Instead, by making s_maxStackLength a static, only one s_maxStackLength gets created regardless of how many Stack objects we create, so we only pay the 4 bytes to hold the constant once per program, not once per Stack object created.

          • Silviu

            Thank you, it's saves memory and the static word has more meanings:
            - like holding a value trough the life of the program
            - doesn't creates duplicates every time.(so it works like a reference or a global variable)
            (i hope i'm not wrong)
            Probably i should expect more of this in c++...
            The member variable m_next doesn't waste memory ? Why we don't use a reference.

            • Alex

              Yes, a static member variable works like a global variable that is namespaced to the class itself.

              m_next doesn't "waste" memory because each Stack independently needs to track its length -- m_next does this.

              Why don't we use a reference for what?

              • Silviu

                Thank you for all the answers. I was meaning reference too m_next, but since i don't know how classes work yet, i'm a little confused.I will take my time with these, but thank you.

Leave a Comment

Put all code inside code tags: [code]your code here[/code]