Inheritance: "A" is an unavailable base of "B"
$ cat inheritance.cpp #include <iostream> using namespace std; class A { }; class B : private A { }; int main() { A* ab = new B; } $ $ g++ inheritance.cpp inheritance.cpp: In function 'int main()': inheritance.cpp:9: error: 'A' is an inaccessible base of 'B' $ I just do not understand this error.
As I understand it, and as this tutorial confirms, private inheritance should only change how class B members are visible to the outside world.
I think the private specifier does more than just change the visibility of class B members.
- What will I get this error and what does it mean?
- Basically, what is wrong if you allow this type of C ++ code? It looks completely harmless.
Having made inheritance private, you basically say that even the fact that B inherits from A (in general) is closed - inaccessible / visible to the outside world.
Without going into a lengthy discussion of what will happen if it is allowed, the simple fact is that it is not allowed. If you want to use the base pointer to refer to an object of a derived type, then you are pretty much stuck using shared inheritance.
Edit: since someone went to send an email to ask for more information about what might happen if this is allowed, I think I will describe it a bit.
The main problem is that private inheritance does not have to follow the principle of Liskov substitution. Open inheritance claims that a derived object can be replaced with an object of a base class, and the correct semantics will continue to arise. However, private inheritance is not approved. The usual description of a relationship implied by private inheritance is "implemented in terms."
Open inheritance means that the derived class supports all the capabilities of the base class and potentially additionally adds. Private inheritance often means more or less the opposite: a derived class uses a common base class to implement something with a more limited interface.
For example, suppose containers in the C ++ standard library were implemented using inheritance rather than templates. On the current system, std::deque and std::vector are containers, and std::stack is a container adapter, which provides a more limited interface. Since it is template-based, you can use std::stack as an adapter for std::deque or std::vector .
If we wanted to provide essentially the same thing with inheritance, we would probably use private inheritance, so std::stack would look something like this:
class stack : private vector { // ... }; In this case, we definitely do not want the user to be able to control our stack , as if it were vector . This can (and most likely will) violate the expectations of the stack (for example, the user could insert / delete elements in the middle, and not just in the form of a stack, as was supposed). We mainly use vector as a convenient way to implement our stack, but if (for example) we change the implementation for stack autonomously (without depending on the base class) or reimplement it in terms of std::deque , we donβt want this to affect any client code - to the client code, it should be just a stack, and not some specialized version of the vector (or deque).
private inheritance should only change how members of class B are visible to the outside world
This is true. And if
A* p = new B; then the inherited members of any B can be accessed from the outside world simply by creating A* . Since they are privately inherited, this access is illegal, and overflow occurs as well.
clang++ gives a slightly more understandable error message:
example.cpp:9:13: error: cannot cast 'B' to its private base class 'A' A* ab = new B; ^ example.cpp:6:11: note: declared private here class B : private A { }; ^~~~~~~~~ 1 error generated. I am not an expert in C ++, but it seems like this is simply not allowed. I will go around the specs and see what I came up with.
Edit: here is the corresponding link from the specification - 4.10 Conversion of pointers , clause 3:
A value of type "pointer to cv
D", whereDis the class type, can be converted to a prvalue of type "pointer to cvB", where B is the base class ofDIfBis an inaccessible or ambiguous base classD, a program that requires this conversion is poorly formed.
It's quite simple: the fact that A inherited privately means that the fact that B extends A is a secret and only B "knows" it. This is the very definition of private inheritance.
Private inheritance means that information about inheritance is hidden outside the derived class. This means that you cannot attribute a derived class to a base class: the relation is unknown to the caller.