8.4 — Access functions and encapsulation

Why make member variables private?

In the previous lesson, we mentioned that class member variables are typically made private. Developers who are learning about object-oriented programming often have a hard time understanding why you’d want to do this. To answer that question, let’s start with an analogy.

In modern life, we have access to many electronic devices. Your TV has a remote control that you can use to turn the TV on/off. You drive a car (or scooter) to work. You take a picture on your smartphone. All three of these things use a common pattern: They provide a simple interface for you to use (a button, a steering wheel, etc…) to perform an action. However, how these devices actually operate is hidden away from you. When you press the button on your remote control, you don’t need to know what it’s doing to communicate with your TV. When you press the gas pedal on your car, you don’t need to know how the combustion engine makes the wheels turn. When you take a picture, you don’t need to know how the sensors gather light into a pixellated image. This separation of interface and implementation is extremely useful because it allows us to use objects without understanding how they work. This vastly reduces the complexity of using these objects, and increases the number of objects we’re capable of interacting with.

For similar reasons, the separation of implementation and interface is useful in programming.


In object-oriented programming, Encapsulation (also called information hiding) is the process of keeping the details about how an object is implemented hidden away from users of the object. Instead, users of the object access the object through a public interface. In this way, users are able to use the object without having to understand how it is implemented.

In C++, we implement encapsulation via access specifiers. Typically, all member variables of the class are made private (hiding the implementation details), and most member functions are made public (exposing an interface for the user). Although requiring users of the class to use the public interface may seem more burdensome than providing public access to the member variables directly, doing so actually provides a large number of useful benefits that help encourage class re-usability and maintainability.

Note: The word encapsulation is also sometimes used to refer to the packaging of data and functions that work on that data together. We prefer to just call that object-oriented programming.

Benefit: encapsulated classes are easier to use and reduce the complexity of your programs

With a fully encapsulated class, you only need to know what member functions are publicly available to use the class, what arguments they take, and what values they return. It doesn’t matter how the class was implemented internally. For example, a class holding a list of names could have been implemented using a dynamic array of C-style strings, std::array, std::vector, std::map, std::list, or one of many other data structures. In order to use the class, you don’t need to know (or care) which. This dramatically reduces the complexity of your programs, and also reduces mistakes. More than any other reason, this is the key advantage of encapsulation.

All of the classes in the C++ standard library are encapsulated. Imagine how much more complicated C++ would be if you had to understand how std::string, std::vector, or std::cout were implemented in order to use them!

Benefit: encapsulated classes help protect your data and prevent misuse

Global variables are dangerous because you don’t have strict control over who has access to the global variable, or how they use it. Classes with public members suffer from the same problem, just on a smaller scale.

For example, let’s say we were writing a string class. We might start out like this:

These two variables have an intrinsic connection: m_length should always equal the length of the string held by m_string (this connection is called an invariant). If m_length were public, anybody could change the length of the string without changing m_string (or vice-versa). This would put the class into an inconsistent state, which could cause all sorts of bizarre problems. By making both m_length and m_string private, users are forced to use whatever public member functions are available to work with the class (and those member functions can ensure that m_length and m_string are always set appropriately).

We can also help protect the user from mistakes in using our class. Consider a class with a public array member variable:

If users can access the array directly, they could subscript the array with an invalid index, producing unexpected results:

However, if we make the array private, we can force the user to use a function that validates that the index is valid first:

In this way, we’ve protected the integrity of our program. As a side note, the at() functions of std::array and std::vector do something very similar!

Benefit: encapsulated classes are easier to change

Consider this simple example:

While this program works fine, what would happen if we decided to rename m_value1, or change its type? We’d break not only this program, but likely most of the programs that use class Something as well!

Encapsulation gives us the ability to change how classes are implemented without breaking all of the programs that use them.

Here is the encapsulated version of this class that uses functions to access m_value1:

Now, let’s change the class’s implementation:

Note that because we did not alter the prototypes of any functions in our class’s public interface, our program that uses the class continues to work without any changes.

Similarly, if gnomes snuck into your house at night and replaced the internals of your TV remote with a different (but compatible) technology, you probably wouldn’t even notice!

Benefit: encapsulated classes are easier to debug

And finally, encapsulation helps you debug the program when something goes wrong. Often when a program does not work correctly, it is because one of our member variables has an incorrect value. If everyone is able to access the variable directly, tracking down which piece of code modified the variable can be difficult (it could be any of them, and you’ll need to breakpoint them all to figure out which). However, if everybody has to call the same public function to modify a value, then you can simply breakpoint that function and watch as each caller changes the value until you see where it goes wrong.

Access functions

Depending on the class, it can be appropriate (in the context of what the class does) for us to be able to directly get or set the value of a private member variable.

An access function is a short public function whose job is to retrieve or change the value of a private member variable. For example, in a String class, you might see something like this:

getLength() is an access function that simply returns the value of m_length.

Access functions typically come in two flavors: getters and setters. Getters (also sometimes called accessors) are functions that return the value of a private member variable. Setters (also sometimes called mutators) are functions that set the value of a private member variable.

Here’s a sample class that has getters and setters for all of its members:

The Date class above is essentially an encapsulated data struct with a trivial implementation, and a user of the class might reasonably expect to be able to get or set the day, month, or year.

The MyString class above isn’t used just to transport data -- it has more complex functionality and has an invariant that needs to be maintained. No setter was provided for variable m_length because we don’t want the user to be able to set the length directly (length should only be set whenever the string is changed). In this class, it does make sense to allow the user to get the string length directly, so a getter for the length was provided.

Getters should provide “read-only” access to data. Therefore, the best practice is that they should return by value or const reference (not by non-const reference). A getter that returns a non-const reference would allow the caller to modify the actual object being referenced, which violates the read-only nature of the getter (and violates encapsulation).

Best practice: Getters should return by value or const reference

Access functions concerns

There is a fair bit of discussion around in which cases access functions should be used or avoided. Although they don’t violate encapsulation, some developers would argue that use of access functions violates good OOP class design (a topic that could easily fill an entire book).

For now, we’ll recommend a pragmatic approach. As you create your classes, consider the following:

  • If nobody outside your class needs to access a member, don’t provide access functions for that member.
  • If someone outside your class needs to access a member, think about whether you can expose a behavior or action instead (e.g. rather than a setAlive(bool) setter, implement a kill() function instead).
  • If you can’t, consider whether you can provide only a getter.


As you can see, encapsulation provides a lot of benefits for just a little bit of extra effort. The primary benefit is that encapsulation allows us to use a class without having to know how it was implemented. This makes it a lot easier to use classes we’re not familiar with.

8.5 -- Constructors
8.3 -- Public vs private access specifiers

118 comments to 8.4 — Access functions and encapsulation

  • :|

    Can you get a getter and a setter in a same function inside a class?

    • Alex

      Yes. A function that returns a non-const reference to a member variable can be used as both a getter and a setter. But you're not getting any encapsulation out of doing such a thing, so it's better to separate them.

  • I tried doing this and it compiles fine but it crashes when I run it. Here's a screenshot
    [img][/img] Thank you for attempting to help me! :)

  • manikanth

    Hello Alex,
    i have a confusion is it recommended to initialize different datatypes in one set function and later we do get in multiple get functions?

    • Alex

      No. Setters generally only set one piece of data. More often you'll use constructors (covered in the next lesson) to initialize your class data (in one go). Then you can use setters to allow users of the class to tweak class data (if that's desired).

  • Chuck

    Alex,   Thank You!  Your suggestion to put the opening of the file (for writing) code into the public arena did the trick.  Am keeping reading.
    Your approach to communicating in these tutorials is superb.

  • Chuck

         I am in the midst of trying to understand how a 'class' functions and what capabilities a 'class' possesses.  I noticed that none of the examples you provided have any activity in the 'private' access area, at least none that I have come across; they all appear to have only the declaration  of variables,etc.  I am trying to open a text file for output and I would like to 'hide' the actual 'opening' (with the appropriate error handling code as well) inside the 'private' section.

    I have been unsuccessful so far.  Please see the included code snippet, along with the compiler error message.  Also, if I can actually hide the 'opening' of the text file for output in the first place,  will the file remain open between instantiations of the class??  My thought aims at trying to reduce the number of times the output file is opened and closed throughout the life of any program as that seems to me to be an expensive time consumer.

    I am using the Dev-C++ 5.11 IDE.

    Thank you in advance for any help you can send my way!!

    [Error] 'm_writetf' does not name a type    [/Error]

  • Dexter

    // alex how can I use friend functions here

  • Mike

    Alex please help and merry Christmas

    • Alex

      What problem are you running into here? The program compiles and works (e.g. if I input "This one", it outputs "This one").

      • Mike

        In my visual studio is >> >> item.address along with

        Os << << " "<<hi.address

        Shows an error

        No operator ">>" matches these operands
        Operand types are std::Istream >> std::string

  • Matt

    Under "Benefit: encapsulated classes are easier to change", 2nd paragraph, there is an extra "are".

  • ali

    hi Alex you have said  "Imagine how much more complicated C++ would be if you had to understand how std::string, std::vector, or std::cout were implemented in order to use them!"
    i want to know how std::cout implemented tell me where to look for that kind of information. This may be funny, but I have a small dream to make my own compiler hhhhh, just for simple operations I just want to understand the principle.

  • Max

    In the last example, I do not understand why the getter functions come before the setter functions. I thought C++ runs from top to bottom, so how would it be able to return a value in the getter function if no setter function defined the rule to retrive the private members yet?

    • Alex

      C++ does compile files from top to bottom. However:
      1) The ordering of functions within a class doesn't matter.
      2) The class is just a definition, it's not actually executing anything itself until the code is run.
      3) The getter function doesn't use the setter function, so there's no dependency there.

  • Lam Gia Khang

    I just want to notice you about a small mistake: the semicolon after "}" of main() in your above examples.
    What a great tutorial! Thanks a lot, Alex!

  • Darren

    Regarding class definition layout. I've seen a number of libraries that put the interface section of the class (i.e. constructors, and member functions) at the top of the class definition, with the internal stuff (i.e. private data members) at the bottom. Does this lend any advantage to code readability, usability, and maintainability? Or is it just a matter of preference?

    • Alex

      It's a matter of preference. There is a fair argument to be made for putting your public interface at the top of the class, where the consumers of your class are likely to look for it first. But that said, it's not hard to skip past the private (and protected) members if they're clustered together.

      If I was going to retrain my brain, I'd probably put my public interfaces first. But I tend to write my classes in thought order rather than optimal consumption order.

  • Matt

    Alex. I'm following you for a few months now and Learncpp is my first resource when in need to revise anything, all in all good job!

    Anyway to the point. As a rule of thumb, does it make sense to have private getters/setters for managing internal class workings as well?

    • Alex

      Not usually. Getters and setters are typically used to allow external classes to get and set data in the class. Since internal members can do that directly, there's usually no need.

      The exception case would be if getting or setting a variable was non-trivial (e.g. if setting a value could cause dynamic reallocation to occur, for example). In that case, it might make sense to write a "set" function of some kind to handle all of that logic (whether you expose this function as public or private depends on your needs).

  • Matt

    Found another typo: "getLength() is an access function that simply returns the value of m_nLength."

    In the example, it returns the value of m_length.

  • Naga Pushkal

    Hi Alex,

    Can you please explain what is the difference between Abstraction and Encapsulation in OOP? I have gone through many sites to find the answer but none of them explained it clearly.

    • Alex

      Sure. Encapsulation generically refers to the process of enclosing one or more items inside a container (such as a function, array, or class). In C++, it specifically refers to the mechanism for restricting access to some of an object's components (data or functions). A class encapsulates its members, using access specifiers to control access. You work with the object through the public interface. This interface generally requires no knowledge of how the object is implemented internally to use.

      Some people also define encapsulation as the binding of data and behaviors together -- but we just call that object-oriented programming.

      Abstraction, on the other hand, generically means reducing the complexity of something by providing a simplified interface that leaves out complexity that may be too much to deal with or irrelevant. For example, a remote control provides an abstraction for the physical circuitry required to send a message to the TV to change the channel.

      In C++, abstraction also is typically used to refer to virtual functions or interface (pure virtual) classes. These allow you to create interfaces for something without regard to how they're implemented.

  • Methos

    I've been using these lessons for a while and have done quite a bit of Get/Set functions in the project I'm working on, but have run into a snag. I'm trying to generate a maze to explore and as part of that, I have the following:

    (there's more to that)

    And a series of functions like the following

    I say like, because I've already checked for typos and such (and corrected one unrelated error). Unfortunately, for some reason I cannot determine, SetIsActive() (which looks like that but with the correct variables) does nothing and SetIsPassable() is setting every bool member except m_bIsQuestBoss and m_bMonsterMoved to true. Which then for a variety of reasons stops the maze from being generated.

    I'm certain this is the issue as I've put cout statements in the maze generating code so I can monitor these values.

    Anyway I was wondering if you could think of anything that could cause this sort of weirdness. I changed IDE to code blocks in case it was a compiler problem (which maybe I have wrong as it wanted to look for more than one compiler when I installed it), but the error persists.

    • Methos

      Oy, nevermind.

      Apparently half of my Get() functions which were copypasted initially weren't corrected to return the proper variable. Which I would have caught four days ago if I had searched for "passable" on the header file rather than other places I thought the Set function might have appeared.

    • Alex

      I don't think I have enough information to effectively determine what this issue is. The only thing I see that's weird is that your set function returns *this. Normally setters return void. Is your maze a 2d array of MazeTiles?

      • Methos

        The error was in my Getters, a bunch of them were returning m_bIsPassable instead of the variable I meant them to because I managed to copypaste them and change the function names and not the variables.

        The set function returns *this so I can chain a bunch of them on one line where appropriate, so for example in my maze creating function, I have the following

        I then start building the maze from where ever the entrance got put, the above code makes sure that tile is actually in the interior.

        Yes, my Maze is an array of MazeTiles of size Width * Length and sits inside of an object I call MazeData (Place is a MazeData object, pMap is a Maze object pointer) which has member variables for width, length, what direction the player is facing, how many monsters and traps are left, etc.

  • sandip patidar

    Very beautiful way to explain C++.
    You really did excellent Job. Keep it up!!!

  • Nikhil Mittal

    Alex, your tutorials are awesome! I am loving these. Thanx!

  • Rohan

    I have a problem in the following program.....(I am using turbo C++ i.e old version)

    output:Enter number: 10
    You entered: 10
    Now number changed to: -10

    Can you explain the above program? Especially why did we use ABC in passing reference to object?

    • alan


      February 1, 2015 at 7:57 am  · Reply

      Well you wouldn't normally use a getter to actually prompt for data input, it
      is really to return a value to the user and not to output it to the screen.
      But except for a minor difference between compilers that function does work.

      Mainly you asked about why use ABC to pass a reference, its confusing because you call the function
      in main() as obj1.putdata() so it shouldn't have compiled without an argument of type class ABC, though when modified as below
      it does work.
      In essence when you define a function with parameters you have to state the data type e.g. int, double, char etc.
      A class is a new data type defined by you.
      If you want a function to receive a class object by reference then you have to tell the function what to expect, hence
      "ABC &obj" just the same as if want a function to receive say an int by reference you would tell it "int &nNum"

      Hopefully that explains it, however I don't think its what you really want to do, I've added
      another function "change_me()" which I think is what you were trying to do.

      Of course since you defined "int data" as public there is no need for a function anyway, as per my last example.
      #include <iostream>

      using namespace std;

      class ABC
      public:int data;
             void getdata()
                  cout << "Enter the number 10 ";
                 cin >> data; // VS 2013 doesn't accept cout <>, but you missed the prompt anyway
                 cout << "You Entered:" << data;
             void putdata(ABC &obj)
                 cout << "Now number is changed to:" <<;
              void change_me()
                  data = data++ ;
                  cout << "Number is now: " << data ;

      void main()
          ABC obj1;
          obj1.putdata(obj1); // added obj1 as the argument
          cout << "Number is now: " <<;
      output:Enter number : 10
          You entered : 10
          Now number changed to : -10
          Number is now: -9
          Number is now: -8



  • Tonyv

    Great site, though a little less impressed by some of the arguements for access functions. Like, "what happens if one changes the name of a member..." well, what if you change the name of the access function? The debug arguement is better, but a bit arbitrary. Why not use the same argument to put redundant functions all over the place? Best was the string/length example, though only relevent when one has this sort of situation.

    A final grump: c++ is an intrinsicly hard to read language because so often what something means depends on the context. An amusing exercise would be to list all the things "*p" could mean. So while I appreciate the efforts made to improve the "readability" of c++, I read this often enough to think the author(s) consider c++ readability a feature rather than a curse. There are certainly ways to write Chinese to make it more readable, but that does not mean it is a language designed to be easily read.

    • Alex

      > well, what if you change the name of the access function?

      If you change the prototype of any function in your public interface, you risk breaking any programs using the class.

      Fortunately, it's more common to change an implementation than it is to change the name of a function. In the Date class, you could represent the date in any number of ways, but the concept of getting a day, month, or year is still valid regardless of the specific implementation.

      A problem that is more likely to occur is when you extend your class in the future and your public functions need additional arguments that current programs aren't supplying. Fortunately, default parameters can often be of help here.

  • Ramseena M.S

    Now too I didn't understand the real usage of declaring class members private

  • DavidE

    Hey, I have a tip for those who like to consolidate their code. Instead of having both setValue() and getValue() methods, I do this:



    • Alex

      This strikes me as being more complicated than just having discrete getters and setters. In addition, I'm not sure how you'd tell whether a function supported only GET or SET.

    • Trevor

      I agree with Alex, but would like to add additional reasons to keep the Get and Set functions separate.

      In DavidE's example, a call to the set function such as Jack.Wage(SET,50,0) returns a double without actually providing the return value.

      Every call to the combined function requires an extra argument (option) to be provided by the calling code, which adds to the program size and reduces its speed. Also the combined function is slower to get than a dedicated getter function and slower to set than a dedicated setter function because it has to decide which to do every time. As at least one of these functions requires a non-linear program flow (caused by the if statement), the code will not execute as fast as it could otherwise on any CPU with instruction pipelining.

      Also this approach defeats some type checking advantages - code such as Jack.Wage(GET,50,0) will not flag any compile-time errors but is clearly not what was intended - separate functions would reject the get as having too many parameters.

      My advice - keep the functions separate. If the application actually requires a combined function (for example due to an external request), then use it as little as possible and have it call the set or get functions. (This isn't as much of an issue for functions within a class.)


  • yogendra

    great tutorial.....
    It gave me clear idea of what inheritance is and also
    the most basic difference between c and c++ is the
    code maintainability achieved through inheritance

  • AsianBorat

    This tutorial is incredible. This article didn't just explain encapsulation. It gave me a clear example, which FINALLY made me understand why encapsulation is so necessary.

  • Balu Nair

    Hi Alex,

    Your article rocks buddy! This article is such a precious gem.


  • yogal

    Wow, great explanation of encapsulation, and WHY one would use getters/setters instead of directly accessing members!

    One good argument for using encapsulation might be validation. When you have setters set-up you can validate what is passed to members and take appropriate action. Although members have to be of certain type, which provides low-level validation, sometimes you need a more complex requirement!

    Take care and thanks for such a wonderful tutorial!

  • Marko

    Alex just want to say your website is better then most books there and i would dare to say that i will stick to this site now rather then even masterpieces like Stephen's Prata Primer

    The way you explain things with examples and actually sticking to important things without writting novels is something that just works great with my mind.

  • Ngugi Thomas

    You are my best teachers

  • Them damn gnomes!! They get everywhere!

Leave a Comment

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