Broadly speaking, public means everyone is allowed to access, private means that only members of the same class are allowed to access, and protected means that members of subclasses are also allowed.
Both are inheritable but private is accessible in the derived class. D. Both are inheritable but protected is not accessible in the derived class. Explanation: Protected member is inheritable and also accessible in derived class is the difference between protected and private access specifiers in inheritance.
Difference between private and protected membersPrivate members are accessible within the same class in which they are declared. Protected members are accessible within the same class and within the derived/sub/child class. Private members can also be accessed through the friend function.
Private Inheritance is one of the ways of implementing the has-a relationship. With private inheritance, public and protected member of the base class become private members of the derived class. That means the methods of the base class do not become the public interface of the derived object.
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.
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;
};
Base
is also aware that Base
contains publicMember
.Base
contains protectedMember
.Base
is aware of privateMember
.By "is aware of", I mean "acknowledge the existence of, and thus be able to access".
The same happens with public, private and protected inheritance. Let's consider a class Base
and a class Child
that inherits from Base
.
public
, everything that is aware of Base
and Child
is also aware that Child
inherits from Base
.protected
, only Child
, and its children, are aware that they inherit from Base
.private
, no one other than Child
is aware of the inheritance.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.
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.
The table above is interpreted 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
It has to do with how the public members of the base class are exposed from the derived class.
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.
Member in base class : Private Protected Public
Inheritance type : Object inherited as:
Private : Inaccessible Private Private
Protected : Inaccessible Protected Protected
Public : Inaccessible Protected Public
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With