C++ inheritance - inaccessible base?
You have to do this:
class Bar : public Foo
{
// ...
}
The default inheritance type of a class
in C++ is private
, so any public
and protected
members from the base class are limited to private
. struct
inheritance on the other hand is public
by default.
Inaccessible base class despite friendship
The problem is that the conversion from B*
to A*
(the one which requires friendship) does not happen in a member function of C
, but in the context of the code containing b
and c
(i.e. the unrelated function bar()
).
It would work fine if you created a member function in C
accepting a B*
, and then called foo()
from within it. That would have the conversion happen within the context of C
which has the necessary access rights (thanks to friendship).
Inaccessible base during inheritance
A derived class can access only public or protected data members of its own sub-objects of base classes.
In this context
display operator +(complex &c2){
display c3=this->a+c2.a;
return c3;
}
the object c2
is not a sub-object of a derived class. So within the operator you may not access its protected data.
Change the operator the following way
display operator +( const display &c2){
return this->a + c2.a;
}
Inheritance: 'A' is an inaccessible base of 'B'
By making the inheritance private, you're basically saying that even the fact that B inherits from A (at all) is private -- not accessible/visible to the outside world.
Without getting into a long-winded discussion of what would happen if it was allowed, the simple fact is that it's not allowed. If you want to use a pointer to base to refer to an object of derived type, then you're pretty much stuck with using public inheritance.
Private inheritance is not necessarily (or even normally) intended to follow the Liskov substitution principle. Public inheritance asserts that a derived object can be substituted for an object of the base class, and proper semantics will still result. Private inheritance does not assert that though. The usual description of the relationship implied by private inheritance is "is implemented in terms of".
Public inheritance means a derived class maintains all the capabilities of the base class and potentially adds more besides. Private inheritance often means more or less the opposite: that the derived class uses a general base class to implement something with a more restricted interface.
Just for example, let's assume for the moment that the containers in the C++ standard library were implemented using inheritance rather than templates. In the current system, std::deque
and std::vector
are containers, and std::stack
is a container adapter that provides a more restricted interface. Since it is based on templates, you can use std::stack
as an adapter for either std::deque
or std::vector
.
If we wanted to provide essentially the same with inheritance, we would probably use private inheritance, so std::stack
would be something like:
class stack : private vector {
// ...
};
In this case, we definitely do not want the user to be able to manipulate our stack
as if it were a vector
. Doing so could (and likely would) violate the expectations of a stack (e.g., the user could insert/remove items in the middle, rather than a purely stack-like fashion as intended). We're basically using vector
as a convenient way to implement our stack, but if (for example) we changed the implementation for stack
stand alone (with no dependence on a base class) or re-implement it in terms of std::deque
, we do not want that to affect any client code -- to the client code, this is supposed to be just a stack, not some specialized variety of vector (or deque).
C++ boost::bind says inaccessible base class
The using
declaration doesn't define a function. It "declares a name" (not a function!), and unhides base names. It's true that the declaration itself has its own accessibility level, which is why you're using it at all in the first place, but to stress again: The using declaration does not declare a new member function. E.g. C++11 7.3.3/11:
The entity declared by a using-declaration shall be known in the context using it according to its definition at the point of the using-declaration.
"Its definition", in your case, is still void base::test(){}
, and that is the entity that is made known to the derived class and referred to by &derived::test
. You can't get a function pointer of type void(derived:**)()
from this because there is no such function.
When you say &derived::test
, the &
-operator is used, which works like this (5.3.1/3):
The result of the unary
&
operator is a pointer to its operand. The operand shall be an lvalue or a qualified-id. If the operand is a qualified-id naming a non-static memberm
of some classC
with typeT
, the result has type “pointer to member of classC
of typeT
” and is a prvalue designating C::m.
In my interpretation of the above logic, &derived::test
"names the non-static member test
of class base
". [Thanks to @DyP:] The is formalized in 10.2/3:
The lookup set for
f
inC
[...] consists of [...] the declaration set [...]. In the declaration set, using-declarations are replaced by the members they designate
If you really want, you can provide a wrapper like this:
class derived : protected base
{
public:
void test() { base::test(); }
};
(Curiously, that solution actually does hide the base function, which is what we want. Rather than using using
, we use an explicitly qualified name to refer to the base function.)
Downcast: why: ‘A’ is an inaccessible base of ‘B’?
From c++11 N3337 draft (a bit old but it's the one I have lying around) 5.2.9/11 (static_cast):
A prvalue of type “pointer to cv1 B,” where B is a class type, can be
converted to a prvalue of type “pointer to cv2 D,” where D is a class
derived (Clause 10) from B, if a valid standard conversion from
“pointer to D” to “pointer to B” exists (4.10), cv2 is the same
cv-qualification as, or greater cv-qualification than, cv1, and B is
neither a virtual base class of D nor a base class of a virtual base
class of D.
In this case, since you use protected
inheritance there is no valid standard conversion from B
to A
so your static_cast
is illegal (g++ is correct to diagnose it).
In this case since you're providing a c++ wrapper around a C API I think the simplest approach is to just stick with public inheritance and have a small amount of trust that your users won't abuse the C API directly if they've already consciously chosen to use your C++ API
Unexpected inaccessible base (first derived class)
Your example could be narrowed to
D * p_d{nullptr};
B * p_b{p_d};
Casting to private base class is prohibited outside of derived class and derived class's friends scope. Error has nothing to do with constructor (which will work as expected).
You may also want to check some workarounds.
Related Topics
Constant Expression Initializer for Static Class Member of Type Double
C++ Template Copy Constructor on Template Class
Why Do We Actually Need Private or Protected Inheritance in C++
How to Connect MySQL Database Using C++
C++11 Equivalent to Boost Shared_Mutex
Reinterpret_Cast VS. C-Style Cast
I Want to Convert Std::String into a Const Wchar_T *
Specify Template Parameters at Runtime
Avoiding the Tedium of Optional Parameters
How to Set Timeout for Std::Cin
Rvalue to Lvalue Conversion Visual Studio
What Are Declarations and Declarators and How Are Their Types Interpreted by the Standard
Differencebetween Wm_Quit, Wm_Close, and Wm_Destroy in a Windows Program
Boost Asio Ssl Async_Shutdown Always Finishes with an Error
Cmake: Include Library Dependencies in a Static Library