Skip to content

Instantly share code, notes, and snippets.

@joseph-zhong
Created February 11, 2017 20:20
Show Gist options
  • Save joseph-zhong/0aa587ae1b3b5253ced384a62c2e8c98 to your computer and use it in GitHub Desktop.
Save joseph-zhong/0aa587ae1b3b5253ced384a62c2e8c98 to your computer and use it in GitHub Desktop.
To answer that question, I'd like to describe member's accessors first in my own words. If you already know this, skip to the heading "next:".
There are three accessors that I'm aware of: public, protected and private.
Let:
class Base {
public:
int publicMember;
protected:
int protectedMember;
private:
int privateMember;
};
Everything that is aware of Base is also aware that Base contains publicMember.
Only the children (and their children) are aware that Base contains protectedMember.
No one but Base is aware of privateMember.
By "is aware of", I mean "acknowledge the existence of, and thus be able to access".
next:
The same happens with public, private and protected inheritance. Let's consider a class Base and a class Child that inherits from Base.
If the inheritance is public, everything that is aware of Base and Child is also aware that Child inherits from Base.
If the inheritance is protected, only Child, and its children, are aware that they inherit from Base.
If the inheritance is private, no one other than Child is aware of the inheritance.
shareimprove this answer
edited Sep 1 '15 at 20:08
Matt Faus
3,49621330
answered May 13 '09 at 20:49
Anzurio
9,81222640
90
I'd like to add a few words that visibility in C++ is based on class instead of on object, which means that objects of the same class can access each other's private fields without restriction. – Zhe Chen Apr 27 '15 at 13:29
19
If you have a hard time understanding this, read Kirill V. Lyadvinsky's answer, then come back and read this. – type traitor Jun 25 '15 at 22:35
3
This is just another case that illustrates how, for the most part, inheriting from SomeBase is just like a hardcoded way to compose-in an anonymous member of type SomeBase. This, like any other member, has an access specifier, which exerts the same control on external access. – underscore_d Feb 27 '16 at 18:28
@ZheChen if I have objects Tom and Jerry of class Person with private field age how do you access (and modify?) Jerry's age using Tom? – gen Jul 12 '16 at 20:25
1
@gen Of course, you can. cpp.sh/3qyxx – Zhe Chen Jul 14 '16 at 8:39
show 1 more comment
up vote
0
down vote
In simple java programming we find bellow three type of inheritance,
Private Only the class in which it is declared can see it.
Protected Package Private + can be seen by subclasses or package member.
Public Everyone can see it.
The access specifiers can be strictly ordered as,
public > protected > private
where public is least secure and private is highly secure
shareimprove this answer
answered Dec 6 '16 at 11:23
Kedar1442
797
add a comment
up vote
7
down vote
1) Public Inheritance:
a. Private members of Base class are not accessible in Derived class.
b. Protected members of Base class remain protected in Derived class.
c. Public members of Base class remain public in Derived class.
So, other classes can use public members of Base class through Derived class object.
2) Protected Inheritance:
a. Private members of Base class are not accessible in Derived class.
b. Protected members of Base class remain protected in Derived class.
c. Public members of Base class too become protected members of Derived class.
So, other classes can't use public members of Base class through Derived class object; but they are available to subclass of Derived.
3) Private Inheritance:
a. Private members of Base class are not accessible in Derived class.
b. Protected & public members of Base class become private members of Derived class.
So, no members of Base class can be accessed by other classes through Derived class object as they are private in Derived class. So, even subclass of Derived class can't access them.
shareimprove this answer
edited May 30 '16 at 8:44
answered May 26 '16 at 4:42
yuvi
3641314
add a comment
up vote
25
down vote
Member in base class : Private Protected Public
Inheritance type : Object inherited as:
Private : Inaccessible Private Private
Protected : Inaccessible Protected Protected
Public : Inaccessible Protected Public
shareimprove this answer
edited Dec 26 '15 at 18:06
pasha
544418
answered Sep 9 '10 at 5:25
kinshuk4
1,69831731
20
This misleading. Private members of a base class behave quite differently from ordinary private class members--they're not accessible from the derived class at all. I think your column of three "Private" should be a column of "Inaccessible". See Kirill V. Lyadvinsky's answer to this question. – Sam Kauffman Apr 11 '13 at 22:13
add a comment
up vote
913
down vote
class A
{
public:
int x;
protected:
int y;
private:
int z;
};
class B : public A
{
// x is public
// y is protected
// z is not accessible from B
};
class C : protected A
{
// x is protected
// y is protected
// z is not accessible from C
};
class D : private A // 'private' is default for classes
{
// x is private
// y is private
// z is not accessible from D
};
IMPORTANT NOTE: Classes B, C and D all contain the variables x, y and z. It is just question of access.
About usage of protected and private inheritance you could read here.
shareimprove this answer
edited Dec 8 '15 at 14:02
answered Sep 3 '09 at 11:27
Kirill V. Lyadvinsky
65.9k16102188
13
What Anzurio wrote only clicked in conjunction with your answer immediately below. Плус 1. – Iwillnotexist Idonotexist Mar 4 '15 at 4:45
add a comment
up vote
22
down vote
These three keywords are also used in a completely different context to specify the visibility inheritance model.
This table gathers all of the possible combinations of the component declaration and inheritance model presenting the resulting access to the components when the subclass is completely defined.
enter image description here
It reads in the following way (take a look at the first row):
if a component is declared as public and its class is inherited as public the resulting access is public.
An example:
class Super {
public: int p;
private: int q;
protected: int r;
};
class Sub : private Super {};
class Subsub : public Sub {};
The resulting access for variables p, q, r in class Subsub is none.
Another example:
class Super {
private: int x;
protected: int y;
public: int z;
};
class Sub : protected Super {};
The resulting access for variables y, z in class Sub is protected and for variable x is none.
A more detailed example:
class Super {
private:
int storage;
public:
void put(int val) { storage = val; }
int get(void) { return storage; }
};
int main(void) {
Super object;
object.put(100);
object.put(object.get());
cout << object.get() << endl;
return 0;
}
Now lets define a subclass:
class Sub : Super { };
int main(void) {
Sub object;
object.put(100);
object.put(object.get());
cout << object.get() << endl;
return 0;
}
The defined class named Sub which is a subclass of class named Super or that Sub class is derived from the Super class. The Sub class introduces neither new variables nor new functions. Does it mean that any object of the Sub class inherits all the traits after the Super class being in fact a copy of a Super class’ objects?
No. It doesn’t.
If we compile the following code, we will get nothing but compilation errors saying that put and get methods are inaccessible. Why?
When we omit the visibility specifier, the compiler assumes that we are going to apply the so-called private inheritance. It means that all public superclass components turn into private access, private superclass components won't be accessible at all. It consequently means that you are not allowed to use the latter inside the subclass.
We have to inform the compiler that we want to preserve the previously used access policy.
class Sub : public Super { };
Don’t be misled: it doesn’t mean that private components of the Super class (like the storage variable) will turn into public ones in a somewhat magical way. Private components will remain private, public will remain public.
Objects of the Sub class may do "almost" the same things as their older siblings created from the Super class. "Almost" because the fact of being a subclass also means that the class lost access to the private components of the superclass. We cannot write a member function of the Sub class which would be able to directly manipulate the storage variable.
This is a very serious restriction. Is there any workaround?
Yes.
The third access level is called protected. The keyword protected means that the component marked with it behaves like a public one when used by any of the subclasses and looks like a private one to the rest of the world. -- This is true only for the publicly inherited classes (like the Super class in our example) --
class Super {
protected:
int storage;
public:
void put(int val) { storage = val; }
int get(void) { return storage; }
};
class Sub : public Super {
public:
void print(void) {cout << "storage = " << storage;}
};
int main(void) {
Sub object;
object.put(100);
object.put(object.get() + 1);
object.print();
return 0;
}
As you see in the example code we a new functionality to the Sub class and it does one important thing: it accesses the storage variable from the Super class.
It wouldn’t be possible if the variable was declared as private. In the main function scope the variable remains hidden anyway so if you write anything like:
object.storage = 0;
The compiler will inform you that it is an error: 'int Super::storage' is protected.
Finally, the last program will produce the following output:
storage = 101
shareimprove this answer
edited Jul 3 '15 at 10:55
answered Jun 7 '15 at 16:56
BugshotGG
1,90742742
1
First one to mention the lack of a modifier (as in Class : SuperClass) yields private. This is an important piece the others are missing out, along with thorough explanations. +1 – Water Oct 25 '16 at 16:22
add a comment
up vote
4
down vote
Private:
The private members of a base class can only be accessed by members of that base class .
Public:
The public members of a base class can be accessed by members of that base class, members of its derived class as well as the members which are outside the base class and derived class.
Protected:
The protected members of a base class can be accessed by members of base class as well as members of its derived class.
In short:
private: base
protected: base + derived
public: base + derived + any other member
shareimprove this answer
edited Jun 12 '15 at 14:59
Zelldon
3,08131435
answered Jan 6 '10 at 14:04
varun
411
add a comment
up vote
6
down vote
Accessors | Base Class | Derived Class | World
—————————————+————————————+———————————————+———————
public | y | y | y
—————————————+————————————+———————————————+———————
protected | y | y | n
—————————————+————————————+———————————————+———————
private | | |
or | y | n | n
no accessor | | |
y: accessible
n: not accessible
Based on this example for java... I think a little table worth a thousand words :)
shareimprove this answer
edited May 9 '15 at 23:09
answered May 9 '15 at 23:03
Enissay
3,67121130
Java has only public inheritance – Zelldon Jun 12 '15 at 14:01
This not the topic to speak about java but NO, you're wrong... Follow the link in my answer above for details – Enissay Jun 12 '15 at 22:09
You mentioned java so it is the topic. And your example handles the specifiers which use in jaca. The question is about the specifiers for inheritance which are not exist in Java an made a difference. If a field in superclass is public and the inheritance is private the field is only acessible inside the subclass. Outside there is no indication if the subclass extends the superclass. But your table explains only the specifiers for field and methods. – Zelldon Jun 12 '15 at 23:20
add a comment
up vote
2
down vote
I found an easy answer and so thought of posting it for my future reference too.
Its from the links http://www.learncpp.com/cpp-tutorial/115-inheritance-and-access-specifiers/
class Base
{
public:
int m_nPublic; // can be accessed by anybody
private:
int m_nPrivate; // can only be accessed by Base member functions (but not derived classes)
protected:
int m_nProtected; // can be accessed by Base member functions, or derived classes.
};
class Derived: public Base
{
public:
Derived()
{
// Derived's access to Base members is not influenced by the type of inheritance used,
// so the following is always true:
m_nPublic = 1; // allowed: can access public base members from derived class
m_nPrivate = 2; // not allowed: can not access private base members from derived class
m_nProtected = 3; // allowed: can access protected base members from derived class
}
};
int main()
{
Base cBase;
cBase.m_nPublic = 1; // allowed: can access public members from outside class
cBase.m_nPrivate = 2; // not allowed: can not access private members from outside class
cBase.m_nProtected = 3; // not allowed: can not access protected members from outside class
}
shareimprove this answer
answered Feb 24 '15 at 10:05
Prajosh Premdas
4052929
add a comment
up vote
87
down vote
Limiting the visibility of inheritance will make code not able to see that some class inherits another class: Implicit conversions from the derived to the base won't work, and static_cast from the base to the derived won't work either.
Only members/friends of a class can see private inheritance, and only members/friends and derived classes can see protected inheritance.
public inheritance
IS-A inheritance. A button is-a window, and anywhere where a window is needed, a button can be passed too.
class button : public window { };
protected inheritance
Protected implemented-in-terms-of. Rarely useful. Used in boost::compressed_pair to derive from empty classes and save memory using empty base class optimization (example below doesn't use template to keep being at the point):
struct empty_pair_impl : protected empty_class_1
{ non_empty_class_2 second; };
struct pair : private empty_pair_impl {
non_empty_class_2 &second() {
return this->second;
}
empty_class_1 &first() {
return *this; // notice we return *this!
}
};
private inheritance
Implemented-in-terms-of. The usage of the base class is only for implementing the derived class. Useful with traits and if size matters (empty traits that only contain functions will make use of the empty base class optimization). Often containment is the better solution, though. The size for strings is critical, so it's an often seen usage here
template<typename StorageModel>
struct string : private StorageModel {
public:
void realloc() {
// uses inherited function
StorageModel::realloc();
}
};
public member
Aggregate
class pair {
public:
First first;
Second second;
};
Accessors
class window {
public:
int getWidth() const;
};
protected member
Providing enhanced access for derived classes
class stack {
protected:
vector<element> c;
};
class window {
protected:
void registerClass(window_descriptor w);
};
private member
Keep implementation details
class window {
private:
int width;
};
Note that C-style casts purposely allows casting a derived class to a protected or private base class in a defined and safe manner and to cast into the other direction too. This should be avoided at all costs, because it can make code dependent on implementation details - but if necessary, you can make use of this technique.
shareimprove this answer
edited Sep 20 '14 at 13:35
answered Sep 3 '09 at 16:04
Johannes Schaub - litb
352k816921064
6
I think Scott Myers (as much as I like his stuff) has a lot to answer for the general confusion. I now think his analogies of IS-A and IS-IMPLEMENTED-IN-TERMS-OF are in sufficient for what is going on. – DangerMouse Sep 14 '12 at 10:20
add a comment
up vote
-7
down vote
See these codes to understand features of c++ about inheritance... I put the result at the end... Hope it helps.
#include <iostream>
using namespace std;
class A {
private:
void pri();
A(int a);
protected:
virtual void pro() {}
public:
void pub1() { cout<<"A.pub1()\n"; }
virtual void pub2() { cout<<"A.pub2()\n"; }
virtual void pub3() { cout<<"A.pub3()\n"; }
virtual void pub4() { cout<<"A.pub4()\n"; }
virtual void pub5() { cout<<"A.pub5()\n"; }
virtual void pub6() { cout<<"A.pub6()\n"; }
virtual void pub7() { cout<<"A.pub7()\n"; }
virtual void pub8() { cout<<"A.pub8()\n"; }
void pub9() { cout<<"A.pub9()\n"; }
virtual void pub10() { cout<<"A.pub10()\n"; }
void pub11() { cout<<"A.pub11()\n"; }
explicit A() {}
virtual ~A() {}
};
class B : public A {
private:
void pri() { cout<<"B.pri()\n"; }
protected:
virtual void pub4() { cout<<"B.pub4()\n"; }
void pub6() { cout<<"B.pub6()\n"; }
public:
void pro() { cout<<"B.pro() "; B::pri(); }
void pub1() { cout<<"B.pub1()\n"; }
void pub2() { cout<<"B.pub2()\n"; }
void pub5() { cout<<"B.pub5()\n"; }
virtual void pub7() { cout<<"B.pub7()\n"; }
virtual void pub8() { cout<<"B.pub8()\n"; }
virtual void pub9() { cout<<"B.pub9()\n"; }
void pub10() { cout<<"B.pub10()\n"; }
void pub11() { cout<<"B.pub11()\n"; }
explicit B() {}
};
class C : protected B {
public:
void pub4_() { cout<<"C.pub4_() "; B::pub4(); }
virtual void pub5() { cout<<"C.pub5()\n"; }
};
class D : private B {
public:
void pub4_() { cout<<"D.pub4_() "; B::pub4(); }
};
class E : public B {
public:
virtual void pub4() { cout<<"E.pub4()\n"; }
virtual void pub7() { cout<<"E.pub7()\n"; }
virtual void pub8() { cout<<"E.pub8()\n"; }
virtual void pub9() { cout<<"E.pub9()\n"; }
virtual void pub10() { cout<<"E.pub10()\n"; }
virtual void pub11() { cout<<"E.pub11()\n"; }
};
void testClasses() {
A* ap=new B();
ap->pub1(); // == A::pub1() //important
// (new B()).pub1() can't override non-virtual A::pub1() for an A* pointer.
ap->pub2(); // == B::pub2() //important
// (new B()).pub1() can override virtual A::pub1() for an A* pointer.
B b;
b.A::pub1();
b.pro();
B* bp=new B;
bp->pub3();
C c;
//c.pub3(); //error
//c.pub4(); //error
c.pub4_();
c.pub5();
D d;
//d.pub3(); //error
//d.pub4(); //error
d.pub4_();
E e;
//e.pub4(); //error
delete ap;
ap = new E();
ap->pub4();
ap->pub5();
ap->pub6();
ap->pub7();
delete bp;
bp = new E();
e.pub8();
e.A::pub8();
e.B::A::pub8();
e.B::pub8();
ap->pub8();
bp->pub8();
e.pub9();
e.A::pub9();
e.B::A::pub9();
e.B::pub9();
ap->pub9(); // important
bp->pub9();
e.pub10();
e.A::pub10();
e.B::A::pub10();
e.B::pub10();
ap->pub10(); // important
bp->pub10(); // very important... eventhough B::pub10() is non-virtual,
// bp->pub10() != b.pub10();
e.pub11();
e.A::pub11();
e.B::A::pub11();
e.B::pub11();
ap->pub11();
bp->pub11();
delete ap;
delete bp;
return;
}
int main() {
testClasses();
return 0;
}
/////////////////////////////////////////
........
Result :
........
A.pub1()
B.pub2()
A.pub1()
B.pro() B.pri()
A.pub3()
C.pub4_() B.pub4()
C.pub5()
D.pub4_() B.pub4()
E.pub4()
B.pub5()
B.pub6()
E.pub7()
E.pub8()
A.pub8()
A.pub8()
B.pub8()
E.pub8()
E.pub8()
E.pub9()
A.pub9()
A.pub9()
B.pub9()
A.pub9()
E.pub9()
E.pub10()
A.pub10()
A.pub10()
B.pub10()
E.pub10()
E.pub10()
E.pub11()
A.pub11()
A.pub11()
B.pub11()
A.pub11()
B.pub11()
shareimprove this answer
edited Nov 4 '12 at 4:50
Andro Selva
36.6k35150200
answered Dec 17 '11 at 14:33
Eremite
271
add a comment
up vote
16
down vote
Public inheritance models an IS-A relationship. With
class B {};
class D : public B {};
every D is a B.
Private inheritance models an IS-IMPLEMENTED-USING relationship (or whatever that's called). With
class B {};
class D : private B {};
a D is not a B, but every D uses its B in its implementation. Private inheritance can always be eliminated by using containment instead:
class B {};
class D {
private:
B b_;
};
This D, too, can be implemented using B, in this case using its b_. Containment is a less tight coupling between types than inheritance, so in general it should be preferred. Sometimes using containment instead of private inheritance is not as convenient as private inheritance. Often that's a lame excuse for being lazy.
I don't think anyone knows what protected inheritance models. At least I haven't seen any convincing explanation yet.
shareimprove this answer
edited Sep 4 '09 at 9:26
answered Sep 3 '09 at 12:34
sbi
140k36185357
Some says an as a relationship. Like using chair as a hammer. Here chair : protected hammer – Jim Thio Nov 28 '13 at 9:00
when using containment instead of private inheritance is not as convenient as private inheritance? Will you please explain it using an example? – Destructor Nov 6 '15 at 11:06
@Pravasi: If D derives privately from D, it can override virtual functions of B. (If, for example, B is an observer interface, then D could implement it and pass this to functions requiring auch an interface, without everybody being able to use D as an observer.) Also, D could selectively make members of B available in its interface by doing using B::member. Both is syntactically inconvenient to implement when B is a member. – sbi Nov 6 '15 at 12:15
add a comment
up vote
12
down vote
If you inherit publicly from another class, everybody knows you are inheriting and you can be used polymorphically by anyone through a base class pointer.
If you inherit protectedly only your children classes will be able to use you polymorphically.
If you inherit privately only yourself will be able to execute parent class methods.
Which basically symbolizes the knowledge the rest of the classes have about your relationship with your parent class
shareimprove this answer
answered Sep 3 '09 at 11:27
Arkaitz Jimenez
13.5k45588
add a comment
up vote
51
down vote
It has to do with how the public members of the base class are exposed from the derived class.
public -> base class's public members will be public (usually the default)
protected -> base class's public members will be protected
private -> base class's public members will be private
As litb points out, public inheritance is traditional inheritance that you'll see in most programming languages. That is it models an "IS-A" relationship. Private inheritance, something AFAIK peculiar to C++, is an "IMPLEMENTED IN TERMS OF" relationship. That is you want to use the public interface in the derived class, but don't want the user of the derived class to have access to that interface. Many argue that in this case you should aggregate the base class, that is instead of having the base class as a private base, make in a member of derived in order to reuse base class's functionality.
shareimprove this answer
edited May 13 '09 at 21:19
answered May 13 '09 at 20:49
Doug T.
42.2k1695168
10
Better say "public: the inheritance will be seen by everyone". protected: the inheritance will only be seen by derived classes and friends", "private: the inheritance will only be seen by the class itself and friends". This is different from your wording, since not only the members can be invisible, but also the IS-A relation can be invisible. – Johannes Schaub - litb May 13 '09 at 20:59
3
The one time I used private inheritance was to do Just what Doug T describes i.e "you want to use the public interface in the derived class, but don't want the user of the derived class to have access to that interface". I basically used it to seal off the old interface and expose another one through the derived class. – Rich Apr 22 '10 at 22:06
add a comment
up vote
2
down vote
Summary:
Private: no one can see it except for within the class
Protected: Private + derived classes can see it
Public: the world can see it
When inheriting, you can (in some languages) change the protection type of a data member in certain direction, e.g. from protected to public.
shareimprove this answer
answered May 13 '09 at 20:58
Roee Adler
13.8k2283123
add a comment
up vote
7
down vote
Protected data members can be accessed by any classes that inherit from your class. Private data members, however, cannot. Let's say we have the following:
class MyClass {
private:
int myPrivateMember; // lol
protected:
int myProtectedMember;
};
From within your extension to this class, referencing this.myPrivateMember won't work. However, this.myProtectedMember will. The value is still encapsulated, so if we have an instantiation of this class called myObj, then myObj.myProtectedMember won't work, so it is similar in function to a private data member.
shareimprove this answer
answered May 13 '09 at 20:57
Andrew Noyes
3,15111013
add a comment
up vote
2
down vote
It's essentially the access protection of the public and protected members of the base class in the derived class. With public inheritance, the derived class can see public and protected members of the base. With private inheritance, it can't. With protected, the derived class and any classes derived from that can see them.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment