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!
1 2 3 4 5 6 7 |
class Base { private: int m_private; // can only be accessed by Base members and friends (not derived classes) public: int m_public; // can be accessed by anybody }; |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
class Base { public: int m_public; // can be accessed by anybody protected: int m_protected; // can be accessed by Base members, friends, and derived classes private: int m_private; // can only be accessed by Base members and friends (but not derived classes) }; class Derived: public Base { public: Derived() { m_public = 1; // allowed: can access public base members from derived class m_protected = 2; // allowed: can access protected base members from derived class m_private = 3; // not allowed: can not access private base members from derived class } }; int main() { Base base; base.m_public = 1; // allowed: can access public members from outside class base.m_protected = 2; // not allowed: can not access protected members from outside class base.m_private = 3; // not allowed: can not access private members from outside 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?
With a protected attribute in a base class, derived classes can access that member directly. This means that if you later change anything about that protected attribute (the type, what the value means, etc…), you’ll probably need to change both the base class AND all of the derived classes.
Therefore, 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 yourself (and have it not take forever, since the number of derived classes is limited).
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, protected, and private.
To do so, simply specify which type of access you want when choosing the class to inherit from:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
// Inherit from Base publicly class Pub: public Base { }; // Inherit from Base protectedly class Pro: protected Base { }; // Inherit from Base privately class Pri: private Base { }; class Def: Base // Defaults to private inheritance { }; |
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 derived 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 |
Protected | Protected |
Private | Inaccessible |
Here’s an example showing how things work:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
class Base { public: int m_public; protected: int m_protected; private: int m_private; }; class Pub: public Base // note: public inheritance { // Public inheritance means: // Public inherited members stay public (so m_public is treated as public) // Protected inherited members stay protected (so m_protected is treated as protected) // Private inherited members stay inaccessible (so m_private is inaccessible) public: Pub() { m_public = 1; // okay: m_public was inherited as public m_protected = 2; // okay: m_protected was inherited as protected m_private = 3; // not okay: m_private is inaccessible from derived class } }; int main() { // Outside access uses the access specifiers of the class being accessed. Base base; base.m_public = 1; // okay: m_public is public in Base base.m_protected = 2; // not okay: m_protected is protected in Base base.m_private = 3; // not okay: m_private is private in Base Pub pub; pub.m_public = 1; // okay: m_public is public in Pub pub.m_protected = 2; // not okay: m_protected is protected in Pub pub.m_private = 3; // not okay: m_private is inaccessible in Pub |
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.
Protected inheritance
Protected inheritance is the least common 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 |
Protected | Protected |
Private | Inaccessible |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
class Base { public: int m_public; protected: int m_protected; private: int m_private; }; class Pri: private Base // note: private inheritance { // Private inheritance means: // Public inherited members become private (so m_public is treated as private) // Protected inherited members become private (so m_protected is treated as private) // Private inherited members stay inaccessible (so m_private is inaccessible) public: Pri() { m_public = 1; // okay: m_public is now private in Pri m_protected = 2; // okay: m_protected is now private in Pri m_private = 3; // not okay: derived classes can't access private members in the base class } }; int main() { // Outside access uses the access specifiers of the class being accessed. // In this case, the access specifiers of base. Base base; base.m_public = 1; // okay: m_public is public in Base base.m_protected = 2; // not okay: m_protected is protected in Base base.m_private = 3; // not okay: m_private is private in Base Pri pri; pri.m_public = 1; // not okay: m_public is now private in Pri pri.m_protected = 2; // not okay: m_protected is now private in Pri pri.m_private = 3; // not okay: m_private is inaccessible in Pri return 0; } |
To summarize in table form:
Access specifier in base class | Access specifier when inherited privately |
---|---|
Public | Private |
Protected | Private |
Private | Inaccessible |
Private inheritance can be useful when the derived class has no obvious relationship to the base class, but uses the base class for implementation internally. In such a case, we probably don’t want the public interface of the base class to be exposed through objects of the derived class (as it would be if we inherited publicly).
In practice, private inheritance is rarely used.
A final example
1 2 3 4 5 6 7 8 9 |
class Base { public: int m_public; protected: int m_protected; private: int m_private; }; |
Base can access its own members without restriction. The public can only access m_public. Derived classes can access m_public and m_protected.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
class D2 : private Base // note: private inheritance { // Private inheritance means: // Public inherited members become private // Protected inherited members become private // Private inherited members stay inaccessible public: int m_public2; protected: int m_protected2; private: int m_private2; }; |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
class D3 : public D2 { // Public inheritance means: // Public inherited members stay public // Protected inherited members stay protected // Private inherited members stay inaccessible public: int m_public3; protected: int m_protected3; private: int m_private3; }; |
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.
Summary
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 |
Protected | Protected | Private | Protected |
Private | Inaccessible | Inaccessible | Inaccessible |
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).
![]() |
![]() |
![]() |
Thank you for the outstanding website and awesome tutorials. As a newbie OOP programmer, while reading this section I had a suggestion for you that perhaps it is better to explain the interaction between inheritance and access specifiers in the following order:
public -> protected -> private, rather than
public -> private -> protected.
I suggest this because the level of privacy/protection or encapsulation of data gradually increases in the order of public -> protected -> private.
So if you list the access specifiers in all your examples and tables in this order, perhaps it will make it even more clearer to the newcomers. Nevertheless, you have already done a great job and thanks a lot for that.
Noted, thanks for the suggestion!
We all know that Base Class pointer can point to the Derived class object.
But this is happening only when the Derived class is inherited using the Public Access Specifier.
I inherited using the Private Access Specifier. Though the classes are empty and I am not accessing anything, still compiler throws error.
Can you please explain why?
Output:
main.cpp:24:18: error: ‘Base’ is an inaccessible base of ‘Derived’
Base *ptr = new Derived;
Hey!
You wouldn't be able to do anything with a `Base*` to a `Derived` object, because as far as you're concerned, a `Derived` is not a `Base`. You can only use treat `Derived` as a `Base` when the `Derived` inherited publicly.
Thanks for responding.
It is quite evident, that I cannot do anything with Base* until it is derived publicly.
I would like to know WHY should the access specifier for inheritance be only Public, WHY NOT Private/Protected?
And more over I am not accessing any data member/method, I am just making an object and pointing to it.
So, ideally compiler also shouldn't be having any problems.....
Kindly explain the reason
Thanks in-advance.
> I would like to know WHY should the access specifier for inheritance be only Public, WHY NOT Private/Protected?
You can use private and protected inheritance, you just can't treat the derived object as a base.
> I am just making an object and pointing to it
But that object wouldn't make any sense, because there's nothing in it. Looking from the outside, a `Derived` is not a `Base`, so they don't share anything. If the compiler allowed you to create the pointer, you couldn't use it for anything, so there's no reason to allow the creation to begin with.
can any one tell for these question.
what is the access level that has to specified for the class, if the class has to be modified, replaced or eliminated in subsequent release without affecting the existing client and why?
can any one explain.
I did this.
1. How is b able to access base member M?
* Line 28: Initialize your variables with uniform initialization. You used direct initialization.
* Line 5, 18: Initialize your variables with uniform initialization.
@B is an @A, @A has @getA, @getA returns @M.
@B doesn't have direct access to @M. @B has access to @getA.
B has access to geta, which has access to M.
Thank you!
I don't understand why uniform initialization and direct initialization would make a difference here? Would you mind explaining that with an example please?
Isn't this simply the last line that you stated "@B doesn't have direct access to @M. @B has access to @getA"? I mean he basically made a public getter for a private var.
> I don't understand why uniform initialization and direct initialization would make a difference here?
It wouldn't. But there's no reason to use direct initialization, so uniform initialization should be used for consistency.
> Isn't this simply the last line that you stated [...]
A public getter for a private variable is fine, as long as the getter doesn't allow modifications to the variable (ie. return by copy or const). OP returned by copy, so the caller can't directly access @A::M, they can only read its value.
Hey Alex!
You've explained the entire inheritance concept so well. Everytime I need to study the same topic, I just read your explanation again. Thanks for making something as complicated as inheritance damn easy :)
Hi there,
Looks like section "Protected inheritance" is describing "Private inheritance".
+
Am I wrong?
Maybe you missed that D2 and D3 are in "A final example" subsection, not "Protected inheritance"?
Thank you Alex, you're right :)
Hi, Alex,
The code below I wrote failed to compile, can you help me?
I wonder why I can not directly access a.m_x inside setValue?
@B can access it's own members which were inherited from @A, but it can't access private/protected members of other @A objects. Write a getter function for @m_x or add @B::setValue as a friend function of @A.
Hi Alex, in the private section you say
"Private inheritance also ensures the derived class must use the public interface of the base class, ensuring encapsulation is upheld."
But that is not true, right? Because in the example, it clearly shows the derived class not using a public interface and accessing the public and protected variables directly. I know for private variables the derived class must use public access methods but in this case, I assume you are referring to private inheritance which is different.
I agree, that's an error. I've removed the incorrect sentence. Thanks for pointing this out!
I personally just remember the rule: "When inheriting, the "safer" specifier wins and members are set accordingly to the winner."
Hi Alex,
I am confused by the phrase "the public" you're always using in this lesson:
For example:
"The public can only access m_public."
Thank you very much.
Hi Joe!
"the public" is everything outside the class that is not a derived class.
so we cn access public n protected member of class privately in derived class though private inheritance?? right??
Hi Akash!
If I understood your questions, you're right.
The best way to figure it out is by testing it yourself.
"With a protected attribute in a base class, derived classes can access that member directly. This means that if you change anything about that protected attribute (the type, what the value means, etc…), you’ll probably need to change both the base class AND all of the derived classes."
I feel like I've gotten a decent grasp of this article, but this line still confuses me a bit. Protected variables are still inherited, right? So changing the base class would mean all its children would inherit the altered protected variable? Or if you mean changing a parent after a child is already instantiated, meaning the child's attribute wouldn't automatically change, the same holds true for private and public members?
The rest seems understandable to me, but this line makes me doubt whether I understand any of it at all, so I would appreciate salvation from this befuddlement! Thanks!
Yes, I meant if you change the protected variable AFTER the inherited classes have been written. I'll make this clearer.
I'm sorry but I still don't quite understand. What is it about protected variables that makes changes to them not cascade down into child classes? How could an update to the base class not directly change child classes, be the change to protected, public or private member?
Edit: I think I just had An epiphany! Because the children can access the base protected members directly, the protected member is, contrary to its name, vulnerable. Code in the children that targets a protected member still affects it, even if this doesn't make sense with the new changes to said protected member. Do I actually get it now or am I still mistaken?
I think you have it. A protected member is only protected from public interference, not from inherited classes.
So, for example, let's say in your base class you had a member named m_x. If you changed that name to m_y, you'd not only break your base class, you'd break all subclasses that directly accessed that member as well.
Or, if m_x was an double, and you changed it to an int. The subclass might still compile, but even if it does, it may no longer behave appropriately (e.g. doing by integer division instead of floating point division).
Wow, this was one hell of a mind-bending read! Thanks for making things crisp and clear, Alex. Great job :)
You're welcome. Thanks for visiting!
Hi, may i ask so
Am I right about this thanks.
Hi Garyy!
You're correct. If you don't have an IDE at hand you can use one of the many online c++ compilers to test your code.
After fixing the errors in your code
Line 3: Missing colon
Line 15: Missing semicolon
@main: Missing return statement
This is the error produced by g++:
Hi, Nascardrjver,
Thanks so much for your reply and point out the errors! I will definitely use online c++ compiler to test next time! thanks!
Alex,
How inheritance affects static var's and member func's? Static in base class should be static in derived class (regardless of inheritance), since it has no relation to *this. Thanks.
Access to static members is inherited just like normal members.
I ran one small program(mentioned below) to understand Public access specifier .Could not understand how derived class can access private variable(x) of base class through public api(print()) of base class.Compilation error comes if try to access private variable directly from derived class but its accessible through another derived api print().
As you mentioned in tutorial, private members are inaccessible to derived class even inherited publicly.
And Derived object has its own independant memory space where both base portion(inherited) and derived portion resides.
then how private variable which was inaccesible came to derived object memory space.Kindly clarify.
Not sure I understand the question. A derived class has a base portion and a derived portion, right? All of the members defined in the base class stay in the base portion, and all of the members defined in the derived class stay in the derived portion. A public base member is accessible from the derived portion of the class (even though it's in the base portion), because it is public. A private base member is also in the base portion, but is not accessible from the derived portion because the access specifier forbids it.
Thank you for the clarification that indeed is detailed in this lesson.
As I see it, if we regard all the members of the base class as being owned by the child class, we are actually possibly creating a new access type of members in the child class.
These are the inaccessibles.
They are not private to the child class, bcz if they were they were accessible from within it (they were indeed private in the parent class).
So a class can have possibly members that are one of the ***four*** following access types:
a. inaccessible
b. private
c. protected
d. public
Did I get it right this time?
If yes, the inaccessible seems to be a new "membership access type concept" I overlooked until now.
Thank you again.
Right. I prefer the more accurate viewpoint that members of the base class as still owned by the base class, and understand that the child is simply a third type of "viewer" (the other two being the public, and the base class itself). From that viewpoint, members of the base class are owned by the base class, and private members are inaccessible to both the public and derived classes, as they are private to the base class that owns them.
Regarding:
"That is, our derived class publicly inherits the base class..."
does this mean:
"That is, our derived class publicly inherits the base class meaning it inherits only public members of the base class..."
If correct, should this not be stated explicitly?
When I say, "publicly inherits", I mean like this:
The derived class inherits all of the members, even the private ones, and those members keep their same access levels. This means the private members of the base class are inaccessible to the derived class, even though they are still inherited.
Hello, Alex.
In the following short program I name a variable in Derived class with the same name as the one in the Base class, and the function inside Derived class favors its own class 's variable. How can I access the Base 's variable inside the Derived class without using some public function in Base?
#include "stdafx.h"
#include "iostream"
class Base
{
private:
int m_private;
protected:
int m_protected;
public:
int m_public;
Base (int pri = 0, int pro = 0, int pub = 0):
m_private(pri), m_protected(pro), m_public(pub) {}
void print()
{
std::cout << m_private << " " << m_protected << " " << m_public << "\n";
}
};
class Derived: public Base
{
private:
int m_private;
public:
int m_public;
Derived (int pri = 1, int pub = 1): m_private(pri), m_public(pub) {}
void print() { std::cout << m_private << " " << m_public << "\n";}
};
int main()
{
Base b;
b.print();
Derived d;
d.print();
b.print();
return 0;
}
It prints out:
0 0 0
1 1
0 0 0
I know it is confusing and I should have avoided that but just for the sake of learning, please explain. Thank you very much.
Inside of a Derived member function, you can use the Base:: prefix to access Base's version of the member variable. This only works for members you have access to (protected and public, not private).
I figured it out on the later lessons. Thank you for your time. Fantastic tutorial.
Hey Alex,
How much overlap is there with C++'s inheritance access specifiers and other C languages?
I'm not familiar enough with other C-style languages to authoritatively say. But best guess is a lot, though they may only support a subset of the functionality that's available in C++, or do things in a slightly different way (using a different syntax or keyword).
So did all the C languages independently say that OOP would be pretty nice in C and created their own implementations or did they all break off from a main group?
My knowledge of the history of OOP isn't good enough to answer this question. You might be able to glean some insights from Wikipedia's History subsection of the OOP page.
Hey Alex, can you answer a simple query of mine.
can you tell what the output will be and how it came so,
[code]
#include <iostream>
using namespace std;
int main()
{
int a=10;
cout << a <<endl << ++a <<endl <<a; // 11 11 12
return 0;
}
[code]
No. Using a variable that has side effects applied more than once in a given statement will lead to undefined results (different answers on different compilers/architectures). Don't do it.
Hi Alex,
there are confusion in my head about 2 things.
1. can you explain more "So when should I use the protected access specifier?" Section, i don't get it. or give example about it. at paragraph one i confuse, what implementetion? what updates are necessary? what and why it is not take forever? and at paragraph two, what additional work? what update?
2. the last sentence of "Private inheritance" section "the derived class has no visible relationship to the base class" what is visible relationship mean?
Thank you
1) Sure. With a protected attribute in a base class, derived classes can access that member directly. This means that if you change anything about that protected attribute (the type, what the value means, etc...), you'll probably need to change both the base class AND all of the derived classes.
2) A square derived class obviously has a visible (obvious) relationship with a shape base class, since they're conceptually related. If square is publicly inherited from shape, the interface (public functions) of square becomes part of the interface of shape, and both are accessible externally. Now consider a Homework class that holds students names and grades in a map. That Homework class might be implemented using a Map class, but that's just an internal detail. In this case, we probably don't want the interface of the Map class to be accessible through Homework. Inheriting privately accomplishes both this, and ensuring that Homework can only access Map through its public interface, ensuring we don't violate encapsulation (assuming that's important in this context).
I've made a few tweaks to the lesson text to try and make these points clearer. Thanks for the feedback.
Do you have a comment reference to a variable slightly wrong here in the section example for Public Inheritance ? :
Yup, but it's fixed now. Thanks for pointing that out.
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.
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)."
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".
Yup, definitely meant public. Stupid copy/paste errors. Thanks for pointing that out.
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.
Eg:
This doesn't work because the fact that Derived is derived form Base is hidden from the public (since the inheritance is protected).
This is true, but we haven't talked about polymorphism yet. I'll make sure I mention it in those lesson though.
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.
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.
That's awesome tutorial about C++, big thanks
simple & nicely presented the overall view of inheritance access specifier topic..thanks...
Simply the best compilation for inheritance access specifier...