Is Concept of Encapsulation Violated here? - c++

#include<iostream>
class A {
public:
int a;
protected:
void func() {
std::cout<<"protected member"<<endl;
}
};
class B:public A
{
public:
using A::func; //Isn't this violation of encapsulation?
};
int main(){
B b;
b.func();
return 0;
}
Why the above code runs successfully?
Does it not violate the concept of Encapsulation?
Correct me if I am wrong.

This is an interesting question, and I think it highlights an important and often-overlooked aspect of encapsulation in c++.
My answer is that "yes, encapsulation has been violated, but not where you think". The actual violation was in declaring the method to be protected in the first place.
Your code demonstrates nicely the problem with the protected relationship with subclasses... they can de-protect you with ease. Another way of saying this is that if you're going to make a member protected, you may as well make it public because in reality protected is public if your subclasses want it to be.
What does this mean in practice?
It means that if you make a member function protected, it is forever part of your class's interface. Therefore you must treat is as seriously as you would any other public member function and indeed as if it were a public member function.
Which is to say that it should be as stateless as possible, with as few preconditions as possible and should you change the implementation, the logical effect on the object as a whole must remain unchanged.

The example that you are showing is not a violation of encapsulation, because subclasses are allowed to add public members on top of what they inherit, and they also are allowed to access protected members that they inherit.
In your case, B, a subclass of A, decided to add a new member function called func, whose implementation happens to consist of a single invocation of A::func.
Generally, protected members should be regarded part of interface of your class, along with its public members. Despite the fact that their visibility is limited to subclasses, protected members are not part of the class implementation, because any change to protected members naming or semantics need to be coordinated with changes to all subclasses of the class.

Related

For a Nested class in C++ how do you access the private member of enclosed class?

I am a beginner in C++, I had a question regarding nested class in C++, how do you access the protected or private member of an enclosed class?
class A{
class B{
protected:
B(){};
};
B var; <=== error as the constructor B is protected
};
One solution is making constructor of B public, but this exposes it'a scope and other function can instantiate it, which I don't want. What's a way to do deal with this ?
You can use friend class:
class A
{
class B
{
friend class A; //<-- makes A a friend of B
protected:
B(){};
};
B var; //<-- OK
};
I believe the question that was asked does not get at the real issue. It is almost an XY problem, but fortunately it has sufficient hints for the real issue to be deduced. Still, in the interest of propriety, I will address the question that was asked before addressing what I believe is the real issue.
how do you access the protected or private member of an enclosed class?
The same way you grant such access when the classes are not nested: the class with the protected or private member declares the other class (or function) as a friend. Just be aware that this is a bit of a sledgehammer approach, so it is advisable to consider alternatives first.
One solution is making constructor of B public, but this exposes it's scope and other function can instantiate it, which I don't want.
No, it doesn't expose anything outside A. You have declared B as a private type within A, which means only A can reference B. With your current setup, there is no functional difference between making A a friend of B and making all members of B public. In either case, A has full access to B and nothing outside A knows that B exists.
While I suspect that B is supposed to be public, the OP has had days to correct this detail. In addition, the OP posted a new question after this possible oversight was pointed out, so I must conclude that the OP does not regard it as an oversight.
Now we get to what I believe is the real issue: how to construct a public nested class from the outer class without allowing public construction.
What's a way to do deal with this ?
If there is a possibility that B might become a public type at some point (a reasonable thing to guard against), you should consider alternatives to friendship. One alternative is to put the constructor of B under lock-and-key. This could be extended to other private members of B, but that is perhaps not necessary.
One advantage of this approach is that access is granted to only the constructor, not to all private members. This helps preserve encapsulation. Furthermore, this approach allows construction to be handed off to helper functions, such as those from the standard library. For example, an emplace_back method for a standard container could construct a B object as long as the method was given a key. This might be more convenient than relying on friendship, depending on how B objects are to be used.
The key
The "key" is a private class of A. It is likely going to be an empty class, as it does not need functionality. All the key needs to do is exist and be inaccessible outside A.
class A{
private:
class KeyForB {};
// Rest of the definition of A
};
The lock
The "lock" is a constructor that accepts the "key" as a parameter. This parameter will not be used by the constructor; all it does is signify that the caller is allowed to call the constructor.
class B{
public:
/* explicit */ B(KeyForB /* unnamed */) : B() {}
protected:
B() {}
};
There are a few details worth looking at. First, you might have noticed that B just used a private member of A! How? There is a special rule that says that nested classes are considered part of the outer class, and as such they can access the private (and protected) members of the outer class – no friend declaration necessary.
Second, the lock delegates to the protected constructor. This may seem odd, but it does serve a purpose. Not only does it keep the default constructor available to B, but also it allows the compiler to optimize away the lock and key. Consider what would happen if the constructor was so large that the compiler opted to not inline it. If a function is not inlined, then parameters cannot be optimized away. In this case, that would mean that a KeyForB would need to be constructed and placed on the call stack. In contrast, the lock is so simple that it should be inlined under any level of optimization. It gets inlined to a call to B() and the unused KeyForB is eliminated from the executable.
Third, there is a comment acknowledging that some coding guidelines recommend marking as explicit most constructors that take a single parameter. This is sound advice. However, in this case, the only reason to create a KeyForB object is to construct a B object. So in this case, it might be acceptable and convenient to leave this conversion implicit.
Putting it together
The only remaining piece is to write a constructor for A, as the compiler-provided default constructor is deleted because it would be ill-formed.
class A{
private:
class KeyForB {};
//public: // <-- possible future change
class B{
public:
B(KeyForB) : B() {}
protected:
B() {}
};
public:
// Default constructor
A() : var(KeyForB{}) {}
private:
B var;
};
It might be worth noting that if the type of var were to change from B to std::shared_ptr<B>, this approach would not run into "make_shared for friend class throwing error", as giving a key to make_shared would enable construction.

Private inheritance usage as described in "The C++ Programming Language"

In The C++ Programming Language, 4th Edition, at §20.5.2 "Access to Base Class" (page 605), it says (regarding private inheritance):
private bases are most useful when defining a class by restricting
the interface to a base so that stronger guarantees can be
provided.For example, B is an implementation detail of Z .The Vector
of pointers template that adds type checking to its Vector base
from §25.3 is a good example.
It's not clear what Bjarne Stroustrup is trying to say here. How can be a class be defined by restricting "the interface" to a base? What does he mean by "stronger guarantees"?
Lets take a very simple example:
// A simple class with a *public* member
class A
{
public:
int a;
};
// Use private inheritance
class B : private A
{
public:
int b;
};
// Use public inheritance
class C : public A
{
public:
int c;
};
// ...
B my_b;
my_b.a = 0; // Invalid, the member a is private due to the private inhericance
C my_c;
my_c.a = 0; // Valid, because the inheritance is public
The private inheritance restricts access to the members of the base class. Even if the A::a member variable is public, due to the private inheritance it becomes private in the sub-class B.
Let's stay with the example of the vector. A vector is just a container of Ts. Now let's say you want to build a type that behaves just like a vector, but adds some additional runtime checks. I don't have my copy of TC++PL at hand right now, so let's just make up a constraint: For example, let's say your vector is only allowed to hold even numbers. Attempting to insert an odd number will result in a runtime error. Let's call this new class even_vector and the version without the runtime checks base_vector.
even_vector provides stronger runtime guarantees than base_vector: It is guaranteed that all of its elements are even.
Assuming that your base_vector is designed to work nice as a base class (which std::vector typically does not), you might now be tempted to use public inheritance to implement even_vector in terms of base_vector. After all, the functionality is the same, you simply have some additional runtime checks in the even_vector case on top of the functionality provided by base_vector. However, if you were to use public inheritance here, you would violate the Liskov Substitution Principle: You cannot use an even_vector wherever you use a base_vector. In particular, the even_vector will break in cases where you are inserting odd numbers into a base_vector. This is bad, as now all code that is written for base_vector must account for the fact that some of the base_vectors cannot deal with odd numbers.
With private inheritance you do not have this problem: Here the fact that even_vector inherits from base_vector is a detail of the implementation. Clients cannot use even_vector where a base_vector is expected, so the problem from above does not occur, but we still get the benefits of code reuse.
That being said, using private inheritance for code reuse is a practice that is discouraged by many. An arguably better way would be to use composition here instead, that is, add a private base_vector member to even_vector instead. The advantage of that approach is that it severely reduces coupling between the two classes, as even_vector is no longer able to access any non-public parts of base_vector.
how can be a class be defined by restricting "the interface" to a base?
By making the inheritance private. When the inheritance is private, the interface of the base class is restricted to the member functions and not available outside. The access specifier can be given in the list of bases:
class A : private B
// ^^^^^^^
What does he mean by "stronger guarantees"?
Any guarantee that is not given by the base, or is a superset of a guarantee given by the base.
For example, the guarantee that "behaviour is always well defined" is stronger than "Behaviour is well defined only if input is not null". Another example: "The function does not throw" is stronger than "The function will not throw unless the copy constructor throws".
Allow us to look at a possible situation with interfaces to help build up the picture.
class poison {
public:
virtual void used() = 0;
};
class food {
public:
virtual void eat();
protected:
void poisonConsumed(poison& p);
}
class cheese : public food, private poison {
public:
virtual void eat() override {
poisonConsumed(*this);
}
private:
void used() override;
}
This presents cheese to the outside world as 'not a poison' - ie nothing outside the class can know that it's a poison, and it could be made 'not a poison' to no impact on anything using it.
The cheese however, can pass itself to anything expecting a poison which is then free to call used(); even though it's private in cheese.

C++ protected: fail to access base's protected member from within derived class

Admittedly, this question title sounds pretty much exactly the same as the question you neighbour Mike has repeatedly asked. I found quite a few questions worded the same way, but none was what my question is about.
First of all, I'd like to clarify a few points for the context of this question:
1, c++ access control works on a class basis rather than instance basis. Therefore, the following code is completely valid.
class Base
{
protected:
int b_;
public:
bool IsEqual(const Base& another) const
{
return another.b_ == b_; // access another instance's protected member
}
};
2, I completely understand why the following code is NOT valid - another can be a sibling instance.
class Derived : public Base
{
public:
// to correct the problem, change the Base& to Derived&
bool IsEqual_Another(const Base& another) const
{
return another.b_ == b_;
}
};
Now time to unload my real question:
Assume in the Derived class, I have an array of Base instances. So effectively, Derived IS A Base(IS-A relation), and Derived consists of Base(Composite relation). I read from somewhere that this(refers to the design of both IS-A and Has-A) is a design smell and I should never have a scenario like this in the first place. Well, the mathematical concept of Fractals, for example, can be modelled by both IS-A and Has-A relations. However, let's disregard the opinion on design for a moment and just focus on the technical problem.
class Derived : public Base
{
protected:
Base base_;
public:
bool IsEqual_Another(const Derived& another) const
{
return another.b_ == b_;
}
void TestFunc()
{
int b = base_.b_; // fail here
}
};
The error message has already stated the error very clearly, so there's no need to repeat that in your answer:
Main.cpp:140:7: error: ‘int Base::b_’ is protected
int b_;
^
Main.cpp:162:22: error: within this context
int b = base_.b_;
Really, according to the following 2 facts, the code above should work:
1, C++ access control works on class basis rather than instance basis(therefore, please don't say that I can only access Derived's b_; I can't access a stand alone Base instance's protected members - it's on class basis).
2, Error message says "within this context" - the context is Derived(I was trying to access a Base instance's protected member from within Derived. It's the very feature of a protected member - it should be able to be accessed from within Base or anything that derives from Base.
So why is the compiler giving me this error?
The access rules could in principle have provided an exemption for this special case, where it's known that Base is the most derived class, the dynamic type of the object. But that would have complicated things. C++ is sufficiently complicated.
A simple workaround is to provide a static protected accessor function up in Base.
A more hack'ish workaround is to use the infamous type system loophole for member pointers. But I'd go for the static function, if I had to stick with the basic design. Because I think like there's not much point in saving a few keystrokes when the resulting code is both hard to get right in the first place, and hard to understand for maintainers.
Concrete example:
class Base
{
protected:
int b_;
static
auto b_of( Base& o )
-> int&
{ return o.b; }
public:
auto IsEqual( const Base& another ) const
-> bool
{
return another.b_ == b_; // access another instance's protected member
}
};
2, Error message says "within this context" - the context is Derived(I was trying to access a Base instance's protected member from within Derived. It's the very feature of a protected member- it should be able to be accessed from within Base or anything that derives from Base.
Okay, had to go to the standard for this one.
So you're asking, "Why isn't it possible?" The answer: Because of how the standard really defines protected member access:
§ 11.4
Protected member access
[1]
An additional access check beyond those described earlier in Clause 11 is applied when a non-static data
member or non-static member function is a protected member of its naming class...As described
earlier, access to a protected member is granted because the reference occurs in a friend or member of some class C.
(emphasis mine)
So let's go over your examples to see what's what.
class Base
{
protected:
int b_;
public:
bool IsEqual(const Base& another) const
{
return another.b_ == b_; // access another instance's protected member
}
};
No problem. another.b_ is Base::b_, and we're accessing it from a member function Base::IsEqual(const Base&) const.
class Derived : public Base
{
public:
// to correct the problem, change the Base& to Derived&
bool IsEqual_Another(const Base& another) const
{
return another.b_ == b_;
}
};
Here, we're accessing Base::b_ again, but our context is a member function Derived::IsEqual_Another(const Base&) const, which isn't a member of Base. So no go.
Now for the alleged culprit.
class Derived : public Base
{
protected:
Base bases_[5];
public:
bool IsEqual_Another(const Derived& another) const
{
return another.b_ == b_;
}
void TestFunc()
{
int b = bases_[0].b_; // fail here
}
};
bases_[0].b_ is accessing the protected Base::b_, inside the context of Derived::TestFunc(), which isn't a member (or friend...) of Base.
So looks like the compiler is acting in accordance with the rules.
I am just turning my comments into an answer because I find the issue interesting. In particular that in the following minimal example D doesn't compile baffled me:
class B { protected: int i; };
class D : public B { int f(B &b){ return b.i; } };
After all, a D is a B and should be able to do all that a B can do (except access B's private members), shouldn't it?
Apparently, the language designers of both C++ and C# found that too lenient. Eric Lippert commented one of his own blog posts saying
But that’s not the kind of protection we’ve chosen as interesting or valuable. "Sibling" classes do not get to be friendly with each other because otherwise protection is very little protection.
EDIT:
Because there seems to be some confusion about the actual rule laid forth in 11.4 I'll parse it and illustrate the basic idea with a short example.
The purpose of the section is laid out, and what it applies to (non-static members).
An additional access check beyond those described earlier in Clause 11
is applied when a non-static data member or non-static member function
is a protected member of its naming class (11.2)
The naming class in the example below is B.
Context is established by summarising the chapter so far (it defined access rules for protected members). Additionally a name for a "class C" is introduced: Our code is supposed to reside inside a member or friend function of C, i.e. has C's access rights.
As described earlier, access to a protected member is
granted because
the reference occurs in a friend or member of some
class C.
"Class C" is also class C in the example below.
Only now the actual check is defined. The first part deals with pointers to members, which we ignore here. The second part concerns your everyday accessing a member of an object, which logically "involve a (possibly implicit) object expression".
It's just the last sentence which describes the "additional check" this whole section was for:
In this case, the class of the object expression
[through which the member is accessed -pas]
shall be C or a class derived from C.
The "object expression" can be things like a variable,
a return value of a function, or a dereferenced pointer.
The "class of the object expression" is a compile time
property, not a run time property; access through one
and the same object may be denied or granted depending
on the type of the expression used to access the member.
This code snippet demonstrates that.
class B { protected: int b; };
class C: public B
{
void f()
{
// Ok. The expression of *this is C (C has an
// inherited member b which is accessible
// because it is not declared private in its
// naming class B).
this->b = 1;
B *pb = this;
// Not ok -- the compile time
// type of the expression *pb is B.
// It is not "C or a class derived from C"
// as mandated by 11.4 in the 2011 standard.
pb->b = 1;
}
};
I initially wondered about this rule and assume the following rationale:
The issue at hand is data ownership and authority.
Without code inside B explicitly providing access (by making C a friend or by something like Alf's static accessor) no other classes except those who "own" the data are allowed to access it. This prevents gaining illicit access to the protected members of a class by simply defining a sibling and modifying objects of the original derived class through the new and before unknown sibling. Stroustrup speaks of "subtle errors" in this context in the TCPPL.
While it would be safe to access (different) objects of the original base class from a derived class' code, the rule is simply concerned with expressions (a compile time property) and not objects (a run time property). While static code analysis may show that an expression of some type Base actually never refers to a sibling, this is not even attempted, similar to the rules concerning aliasing. (Maybe that is what Alf meant in his post.)
I imagine the underlying design principle is the following: Guaranteeing ownership and authority over data gives a class the guarantee that it can maintain invariants related to the data ("after changing protected a always also change b"). Providing the possibility to change a protected property from by a sibling may break the invariant -- a sibling does not know the details of its sibling's implementation choices (which may have been written in a galaxy far, far away). A simple example would be a Tetragon base class with protected width and height data members plus trivial public virtual accessors. Two siblings derive from it, Parallelogram and Square. Square's accessors are overridden to always also set the other dimension in order to preserve a square's invariant of equally long sides, or they only just use one of the two. Now if a Parallelogram could set a Square's width or height directly through a Tertragon reference they would break that invariant.
This has nothing to do with bases_ being protected in Derived, it is all about b_ being protected in Base.
As you have already stated, Derived can only access protected members of its base class, not of any other Baseobjects. Not even if they are members of Derived.
If you really need access, you can make Derived a friend on Base.
Ok, I've been bothered by this wicked thing for a night. Endless discussions and the ambiguity of clause 11.4(as quoted by Yam marcovic)
§ 11.4 Protected member access
[1] An additional access check beyond those described earlier in Clause 11 is applied when a non-static data member or non-static member function is a protected member of its naming class...As described earlier, access to a protected member is granted because the reference occurs in a friend or member of some class C.
have burned me out. I decided to resort to the gcc source code(gcc 4.9.2 in my case) to check how those gcc guys understood the clause 11.4, and what check exactly the C++ standards wants to do and how those checks are supposed to be done.
In gcc/cp/search.c:
/* Returns nonzero if it is OK to access DECL through an object
indicated by BINFO in the context of DERIVED. */
static int protected_accessible_p (tree decl, tree derived, tree binfo)
{
access_kind access;
/* We're checking this clause from [class.access.base]
m as a member of N is protected, and the reference occurs in a
member or friend of class N, or in a member or friend of a
class P derived from N, where m as a member of P is public, private
or protected.
Here DERIVED is a possible P, DECL is m and BINFO_TYPE (binfo) is N. */
/* If DERIVED isn't derived from N, then it can't be a P. */
if (!DERIVED_FROM_P (BINFO_TYPE (binfo), derived))
return 0;
access = access_in_type (derived, decl);
/* If m is inaccessible in DERIVED, then it's not a P. */
if (access == ak_none)
return 0;
/* [class.protected]
When a friend or a member function of a derived class references
a protected nonstatic member of a base class, an access check
applies in addition to those described earlier in clause
_class.access_) Except when forming a pointer to member
(_expr.unary.op_), the access must be through a pointer to,
reference to, or object of the derived class itself (or any class
derived from that class) (_expr.ref_). If the access is to form
a pointer to member, the nested-name-specifier shall name the
derived class (or any class derived from that class). */
if (DECL_NONSTATIC_MEMBER_P (decl))
{
/* We can tell through what the reference is occurring by
chasing BINFO up to the root. */
tree t = binfo;
while (BINFO_INHERITANCE_CHAIN (t))
t = BINFO_INHERITANCE_CHAIN (t);
if (!DERIVED_FROM_P (derived, BINFO_TYPE (t)))
return 0;
}
return 1;
}
The most interesting part is this:
if (DECL_NONSTATIC_MEMBER_P (decl))
{
/* We can tell through what the reference is occurring by
chasing BINFO up to the root. */
tree t = binfo;
while (BINFO_INHERITANCE_CHAIN (t))
t = BINFO_INHERITANCE_CHAIN (t);
if (!DERIVED_FROM_P (derived, BINFO_TYPE (t)))
return 0;
}
1) derived in the code is the context, which in my case is the Derived class;
2) binfo in the code represents the instance whose non-static protected member is access, which in my case is base_, Derived's protected data member Base instance;
3) decl in the code represents base_.b_.
What gcc did when translating my code in question was:
1) check if base_.b_ is non-static protected member? yes of course, so enter the if;
2) climb up the inheritance tree of base_;
3) figure out what actual type base_ is; of course, it's Base
4) check if the result in 3) which is Base, derives from Derived. Of course that's a negative. Then return 0 - access denied.
Apparently, according to gcc's implementation, the "additional check" requested by the C++ standard is the type check of the instance through which the protected member gets accessed. Although the C++ standard did not explicitly mention what check should be done, I think gcc's check is the most sensible and plausible one - it's probably the kind of check the C++ standard wants. And then the question really boils down to the rationale for the standard to request an additional check like this. It effectively makes the standard contradict itself. Getting rid of that interesting section(It seems to me that the C++ standard is asking for inconsistency deliberately), the code should work perfectly. In particular, the sibling problem won't occur as it will be filtered by the statement:
if (!DERIVED_FROM_P(BINFO_TYPE(t), derived))
return 0;
Regarding the kind of protection(protected does not work purely on class, but on BOTH class AND instance) mentioned by Peter and the post(by Eric Lippert) he shared, I personally totally agree with that. Unfortunately, by looking at the C++ standard's wording, it doesn't; if we accept that the gcc implementation is an accurate interpretation of the standard, then what the C++ standard really asks for is, a protected member can be accessed by its naming class or anything that derives from the naming class; however, when the protected member is accessed via an object, make sure the owner object's type is the same as the calling context's type. Looks like the standard just wants to make an exception for the clarification point 1 in my original question.
Last but not least, I'd like to thank Yam marcovic for pointing out clause 11.4. You are the man, although your explanation wasn't quite right - the context does not have to be Base, it can be Base or anything derived from Base. The catch was in the type check of the instance through which the non-static protected member was accessed.
There are a couple of long answers, and quotes from the standard that are correct. I intend on providing a different way of looking at what protected really means that might help understanding.
When a type inherits from a different type, it gets a base sub-object. The protected keyword means that any derived type can access this particular member within the sub-object that it contains due to the inheritance relationship. The keyword grants access to specific object(s), not to any object of type base.

private inheritance in C++

I am learning the concepts of OOPS, and came across private inheritance. From what I've learnt - When a class derives from a base class and letter when the derived class is instantiated, the constructor of the Base class is called first, followed by the constructor of the derived class. So, in the code "A created" would be printed first.
The problem is since the inheritance is private, all the members of A would be private inside B, so how can the constructor of A be called when B is instantiated. Going by this logic, the following code should generate errors, but when I run it, it compiles fine, and gives the output "A created" followed by "B created".
How is this happening? Or am I making some mistake in understanding the concept?
#include <iostream>
using namespace std;
class A{
public:
A(void)
{
cout<<"A created"<<endl;
}
~A()
{
//do nothing
}
void doSomething(void)
{
cout<<"hi";
}
};
class B:private A
{
public:
B(void)
{
cout<<"B created"<<endl;
}
~B()
{
//do nothing
}
};
int main() {
B* myptr = new B();
//myptr->doSomething();
delete myptr;
return 0;
}
B can call public (and protected) methods of A, since A constructor is public B can call it.
Please see following link to better understand c++ private inheritance:
Difference between private, public, and protected inheritance
The access specifier for inheritance limits access to code outside the derived class; think to the base class A as if it were a normal private field:" the outside" can't see it, but B can use it freely from "the inside".
As for the constructor, it's implicitly called by B's constructor, so there's no problem (and, besides, otherwise private inheritance would be unusable).
Still, don't worry too much about private inheritance, it's useful in extremely rare cases (I've never seem it actually used in real life, and for this reason many languages don't even support it), normally composition (using a normal private field) is a better and simpler way.
Here is good short article about private inheritance which illustrates in details what is private inheritance, when it is useful and when it should be avoided in favour of inclusion.
In short:
Inheritance access modifier limits access to basic class properties and methods not for derived class but for code which uses derived class.
This is useful to 'replace' (not 'extend') basic class interface for users of inherited class.
In general it's considered better to include basic class member rather than use private inheritance.
If you need to reuse some methods of basic class which rely on virtual functions and you need to override virtual functions (but you still want to hide part of basic class interface from external code), this is more appropriate case for private inheritance.
Hope this will help.

C++ subclassing access modifier?

I'm C++ newbie, and I have many years of experience about OO languages such as C/C#/Objective-C. Now, I'm learning C++.
I saw this C++ code:
class World : public State
{
};
It seems class World inherits the class State publicly.
Public subclassing? It's hard to understand.
What's the concept of this feature?
And when is this useful or required?
The need for the public keyword there is just that for classes defined with the keyword class, the default access modifier (for everything - data members, member functions, and base classes) is private. So
class World : State {};
is the same as:
class World : private State {};
and that's probably not what you want - it means that the base class is only accessible within the class World. Outsiders "don't know" that the inheritance is there at all.
For classes defined with the keyword struct, the default access modifier is public, so you could write:
struct World : State {};
and get something that both looks and behaves a bit like every other language with inheritance. But the struct keyword, and the fact that it defines a class, is really only there for compatibility with C. You won't find many C++ style guides that recommend using it just in order to get the default public accessibility - generally it's used only for classes which are POD, or perhaps only for classes with no member functions at all.
As for why C++ has private inheritance in the first place: for most purposes, private inheritance is a form of composition. Normal composition:
class World {
State state;
public:
void foo() {
state.bar();
state.baz();
and so on
}
};
That is, the class World knows that it's implemented using a State, and the outside world doesn't know how World is implemented.
vs.
class World : private State {
public:
void foo() {
bar();
baz();
and so on
}
};
That is, the class World knows that it's implemented by being a State, and the outside world doesn't know how it's implemented. But you can selectively expose parts of the interface of State by for example putting using State::bar; in the public part of World's definition. The effect is as if you'd laboriously written a function (or several overloads) in World, each of which delegates to the same function on State.
Other than avoiding typing, though, one common use of private inheritance is when the class State is empty, i.e. has no data members. Then if it's a member of World it must occupy some space (admittedly, depending on the object layout this might be space that otherwise would just be padding, so it doesn't necessarily increase the size of World), but if it's a base class then a thing called the "empty base class optimization" kicks in, and it can be zero-size. If you're creating a lot of objects, this might matter. Private inheritance enables the optimization, but the outside world won't infer an "is-a" relationship, because it doesn't see the inheritance.
It's a pretty fine difference - if in doubt just use explicit composition. Introducing inheritance to save typing is all very well until it has some unexpected consequence.
In case
class World: private State
{
};
private inheritance means that all public and protected members of State would be inherited by World and would become private. This seals State inside World. No class that inherits from World will be able access any features of State.
What makes you think that it's private? It says public right there, which means it is publically subclassing.
That aside, what private and protected inheritance do is the same as public inheritance, except that all the member variables are functions are inherited with at least private or protected accessibility. For example, if State had a public member function 'foo()', it would be private in 'World'.
This is rarely used in practice, but it does have purpose. The most common use that I've seen is composition through inheritance. i.e. you want a "has a" relationship rather than an "is a" (that you usually get with public inheritance). By privately inheriting the class, you get all its variables and methods, but you don't expose them to the outside world.
One advantage of using private inheritance for composition comes from the empty base class optimisation (EBCO). Using normal composition, having a member object of an empty class would still use at least 1 byte because all variables must have a unique address. If you privately inherit the object you want to be composed of then that doesn't apply and you won't suffer memory loss.
e.g.
class Empty { };
class Foo
{
int foo;
Empty e;
};
class Bar : private Empty
{
int foo;
};
Here, sizeof(Foo) will probably be 5, but sizeof(Bar) will be 4 because of the empty base class.
The public/protected/private keyword before the name of the ancestor class indicates the desired visibility of members from the ancestor. With private inheritance, the descendant inherits only the implementation from the ancestor, but not the interface.
class A {
public:
void foo();
};
class B : private A {
public:
void bar();
};
void B::bar()
{
foo(); // can access foo()
}
B b;
b.foo(); // forbidden
b.bar(); // allowed
In general, you should use public inheritance because inheritance shouldn't be used for implementation re-use only (which is what private inheritance does).