11.5 — Inheritance and access specifiers

In the previous lessons in this chapter, you’ve learned a bit about how base inheritance works. In all of our examples so far, we’ve used public inheritance. That is, our derived class publicly inherits the base class.

In this lesson, we’ll take a closer look at public inheritance, as well as the two other kinds of inheritance (private and protected). We’ll also explore how the different kinds of inheritance interact with access specifiers to allow or restrict access to members.

To this point, you’ve seen the private and public access specifiers, which determine who can access the members of a class. As a quick refresher, public members can be accessed by anybody. Private members can only be accessed by member functions of the same class or friends. This means derived classes can not access private members of the base class directly!

This is pretty straightforward, and you should be quite used to it by now.

The protected access specifier

When dealing with inherited classes, things get a bit more complex.

C++ has a third access specifier that we have yet to talk about because it’s only useful in an inheritance context. The protected access specifier allows the class the member belongs to, friends, and derived classes to access the member. However, protected members are not accessible from outside the class.

In the above example, you can see that the protected base member m_protected is directly accessible by the derived class, but not by the public.

So when should I use the protected access specifier?

Using the protected access specifier is most useful when you (or your team) are going to be the ones deriving from your own classes, and the number of derived classes is reasonable. That way, if you make a change to the implementation of the base class, and updates to the derived classes are necessary as a result, you can make the updates and have it not take forever.

Making your members private gives you better encapsulation and insulates derived classes from changes to the base class. But there’s also a cost to build a public or protected interface to support all the access methods or capabilities that the public and/or derived classes need. That’s additional work that’s probably not worth it, unless you expect someone else to be the one deriving from your class, or you have a huge number of derived classes, where the cost of updating them all would be expensive.

Different kinds of inheritance, and their impact on access

First, there are three different ways for classes to inherit from other classes: public, private, and protected.

To do so, simply specify which type of access you want when choosing the class to inherit from:

If you do not choose an inheritance type, C++ defaults to private inheritance (just like members default to private access if you do not specify otherwise).

That gives us 9 combinations: 3 member access specifiers (public, private, and protected), and 3 inheritance types (public, private, and protected).

So what’s the difference between these? In a nutshell, when members are inherited, the access specifier for an inherited member may be changed (in the derived class only) depending on the type of inheritance used. Put another way, members that were public or protected in the base class may change access specifiers in the derived class.

This might seem a little confusing, but it’s not that bad. We’ll spend the rest of this lesson exploring this in detail.

Keep in mind the following rules as we step through the examples:

  • A class can always access its own (non-inherited) members.
  • The public accesses the members of a class based on the access specifiers of the class it is accessing.
  • A class accesses inherited members based on the access specifier inherited from the parent class. This varies depending on the access specifier and type of inheritance used.

Public inheritance

Public inheritance is by far the most commonly used type of inheritance. In fact, very rarely will you see or use the other types of inheritance, so your primary focus should be on understanding this section. Fortunately, public inheritance is also the easiest to understand. When you inherit a base class publicly, inherited public members stay public, and inherited protected members stay protected. Inherited private members, which were inaccessible because they were private in the base class, stay inaccessible.

Access specifier in base class Access specifier when inherited publicly
Public Public
Private Inaccessible
Protected Protected

Here’s an example showing how things work:

This is the same as the example above where we introduced the protected access specifier, except that we’ve instantiated the derived class as well, just to show that with public inheritance, things work identically in the base and derived class.

Public inheritance is what you should be using unless you have a specific reason not to.

Rule: Use public inheritance unless you have a specific reason to do otherwise.

Private inheritance

With private inheritance, all members from the base class are inherited as private. This means private members stay private, and protected and public members become private.

Note that this does not affect the way that the derived class accesses members inherited from its parent! It only affects the code trying to access those members through the derived class.

To summarize in table form:

Access specifier in base class Access specifier when inherited privately
Public Private
Private Inaccessible
Protected Private

Private inheritance can be useful when the derived class has no visible relationship to the base class, but uses the base class for implementation internally.

Protected inheritance

Protected inheritance is the last method of inheritance. It is almost never used, except in very particular cases. With protected inheritance, the public and protected members become protected, and private members stay inaccessible.

Because this form of inheritance is so rare, we’ll skip the example and just summarize with a table:

Access specifier in base class Access specifier when inherited protectedly
Public Protected
Private Inaccessible
Protected Protected

A final example

Base can access its own members without restriction. The public can only access m_public. Derived classes can access m_public and m_protected.

D2 can access its own members without restriction. D2 can access Base’s m_public and m_protected members, but not m_private. Because D2 inherited Base privately, m_public and m_protected are now considered private when accessed through D2. This means the public can not access these variables when using a D2 object, nor can any classes derived from D2.

D3 can access its own members without restriction. D3 can access D2’s m_public2 and m_protected2 members, but not m_private2. Because D3 inherited D2 publicly, m_public2 and m_protected2 keep their access specifiers when accessed through D3. D3 has no access to Base’s m_private, which was already private in Base. Nor does it have access to Base’s m_protected or m_public, both of which became private when D2 inherited them.


The way that the access specifiers, inheritance types, and derived classes interact causes a lot of confusion. To try and clarify things as much as possible:

First, a class (and friends) can always access its own non-inherited members. The access specifiers only affect whether outsiders and derived classes can access those members.

Second, when derived classes inherit members, those members may change access specifiers in the derived class. This does not affect the derived classes’ own (non-inherited) members (which have their own access specifiers). It only affects whether outsiders and classes derived from the derived class can access those inherited members.

Here’s a table of all of the access specifier and inheritance types combinations:

Access specifier in base class Access specifier when inherited publicly Access specifier when inherited privately Access specifier when inherited protectedly
Public Public Private Protected
Private Inaccessible Inaccessible Inaccessible
Protected Protected Private Protected

As a final note, although in the examples above, we’ve only shown examples using member variables, these access rules hold true for all members (e.g. member functions and types declared inside the class).

11.6 -- Adding, changing, and hiding members in a derived class
11.4 -- Constructors and initialization of derived classes

49 comments to 11.5 — Inheritance and access specifiers

  • Cornel

  • Priya

    very comprehensive tutorial.. kudos to you!!

  • Amazing Tutorials. No more words.

    I have been working as Software engineer of Real Time Embedded for 7 years and I discovered that there is many things I never knew.

    Thank you

  • Sean

    Very clear, thanks a lot!

  • Ben

    In the first example under the title “Public inheritance” the Pub constructor should be public. Apart from that, great tutorial (judging from what i’ve seen until now).

  • Kinten

    so, private and protected inheritance only differ in classes that are derived more than one time (multiple inheritance), it’s that right?

    • I suppose you could look at it that way. Really the derived class does differ, since members will have different access specifiers. However, as you imply, since private and protected have the same access restrictions within a class, there’s no practical difference until you derive the class again.

      Just so you know, the term multiple inheritance should not be used when referring to a class that has been derived multiple times. It has a different meaning: a class that is derived from multiple parents simultaneously. We cover multiple inheritance in a few more lessons.

  • SureshMP

    It’s very useful doc for those who are beginner in c++.

  • Purushothman

    Excellent article…

    Purushothman J

  • jt

    excellent tutorial…

  • jeremy

  • Hayyan

    Very informative… some stuff i didnt know…thnaks a lot

  • very good example
    here u willget complete view of the exact inheritance is

  • Hazel

    very nice example

  • I have neve seen such a clear definitions and examples before. Thanks Alex!

  • Really amazing tutorial… I got many-things new here…
    thank you very much…..

  • Shalinee Singh

    Very good explanation done. Thanks.

  • Sandeep Aggarwal

    Thanx a tonne..Beautiful Tutorial..Finally understood what all class specifiers are after 3 yeras of graduation??

  • migmar dolma

    thanks it made the topic more clear
    migmar dolma

  • Vikas

    Excellent.. amazing simplicity in way of teaching… kudos to you…

  • Renuka S

  • ozzy

    Very nice explanation !

  • auasp

    Is the first table on Public inheritance correct?
    I think all the entries in “derived access specifier” column should be Public.

  • Rollie

    Great explanation - thanks!

  • shruthi

    Thanks!. Good explanation of the topic.

  • Kevin

    Excellent tutorial.
    The best I’ve seen so far.
    Helped me a lot.
    Thank you!




  • Peter Bulyaki

    Very nice and thorough tutorial, however I found one very misleading point:
    For public inheritance, your table says private will become private in the derived class (and you introduce an extra column to say that it is not accessible in the derved class explicitly). This is anything but true, because private will become *inaccessible* in the derived class - not private. Beginners who would take the easy way of learning, would memorize your tables, and they would easily get confused by it.

    What you say is:
    Public -> Public
    Protected -> Protected
    Private -> Private

    This is how I would change your table, putting a “-” to the appropriate cell:
    public -> public
    protected -> protected
    private -> -

    Same applies to protected inheritance:
    public -> protected
    protected -> protected
    private -> -

    And for private inheritance:
    public -> private
    protected -> private
    private -> -

    So in my interpretation, there is an even easier way to memorize all 3*3 cases:
    First, you’d need to point out, that private is private. No matter how you inherit, a private member will NOT be accessible in the derived class.

    So here it is how I’d let people memorize it:
    0. Inheritance specifier is uninterpretable for private members.

    1. PUBLIC inheritance: Everything remains the SAME in the derived class:
    public -> public
    protected -> protected

    2. PROTECTED inheritance: Everything becomes PROTECTED in the derived class:
    public -> protected
    protected -> protected

    3. PRIVATE inheritance: Everything becomes PRIVATE in the derived class:
    public -> private
    protected -> private

    This is how I was taught it, and I think that it is much simpler this way.

    • Nikhil Singhal

      Thanks Peter

      your comment makes Alex’s article more understandable, specially for Beginners, most of the times they become confused at this point, but if they follow your table they never confused LIKE ME 🙂

      Thanks & Regards
      Nikhil Singhal

    • singhchauhan.nitin

      Peter you made it more clear to understand the hierarchy of inheritance .. thanks a lot..

    • Alex

      Upon reflection, I agree that this way of looking at things is simpler. I’ve updated the lesson to follow this pattern.

  • Matheus

    Thanks for the last example. It was simple concise, and cleared all my doubts about the subject. Keep up with updating your tutorial!! ^^

  • Shree

    Simply the best compilation for inheritance access specifier…

  • pavi

    simple & nicely presented the overall view of inheritance access specifier topic..thanks…

  • That’s awesome tutorial about C++, big thanks

  • Ola Sh

    Hi Alex,

    This lesson was really interesting. Thanks for the good work. There was a typo in this sentence: (Private inheritance, paragraph 2), Note that this does not affect "that" way that the derived class accesses members inherited from its parent! "That" should be "the". Can you give me typical cases where private inheritance would be useful? Thanks.

    • Alex

      Typo fixed. Thanks for noticing.

      Private inheritance is rarely used, and most of the uses for it are advanced C++. For now, it’s good enough just to know it exists.

  • Qisi

    Hi Alex,
    Thanks a lot for this fabulous tutorial!!

    The tables really clear things out!!
    However, I think there’s one more caveat about the inheritance type. Instead of just a easier way of restrict the member access of the class all at once, I think it also influence how public/derived class view the fact of inheritance.


    This doesn’t work because the fact that Derived is derived form Base is hidden from the public (since the inheritance is protected).

  • Matt

    In section "Public inheritance", in the code example, in the declaration of "class Pub", you wrote a comment:
    "// note: private inheritance".

    I think you meant "public inheritance".

  • Rakesh

    Is the effect of the inheritance type applied to member variables only or even to the member functions??

    I haven’t seen that been mentioned anywhere.

    • Alex

      The final line of the lesson has the answer:

      “As a final note, although in the examples above, we’ve only shown examples using member variables, these access rules hold true for all members (e.g. member functions and types declared inside the class).”

Leave a Comment

Put C++ code inside [code][/code] tags to use the syntax highlighter