Inheritance: 'A' Is an Inaccessible Base of 'B'

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).

error: 'A' is an inaccessible base of 'B'

If you want polymorphic pointer conversion to work outside the class, then the inheritance must be public. There is no way to work around that.

You could add a member function that does the polymorphic pointer conversion within the class:

class B : private A{
// ...
public:
A* getA() {
return this;
}
};

Which allows you to do this, while still allowing private inheritance:

B* b_ptr = new B("c++");
A* ptr = b_ptr->getA();
// ptr = b_ptr; // only allowed in member functions

I haven't encountered a real world design where this trick would be useful, but suit yourself.


PS. Remember that you should destroy objects that you create. Also do realize that delete ptr has undefined behaviour, unless ~A is virtual.

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.

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

Why am I getting the error A is an inaccessible base of B when using dynamic_cast and templates?

The default class inheritance is private (class B : A {}; defaults to class B : private A {};).

So you can't handle b through type A.

EDIT:
Like Rob said :), the way to fix it is by using public inheritance:

class B : public A {};

EDIT:

The relationship between a publicly derived class and its base class is "is a", meaning that it is a specialization of a more generic type, and as such, it implements the behavior of that generic class and possibly more.

The relationship between a privately derived class and its base class is "implemented in terms of". It prevents objects from being considered extensions of the base class. A good example of its use is boost::noncopyable that prevents objects of a privately derived class from being copied.
http://www.boost.org/doc/libs/1_52_0/libs/utility/utility.htm#Class_noncopyable

In the hypothetical case that the requirements include private inheritance and at some point a function is created that wants to reference the object as its base, a public method returning a casted to base class pointer this will do it much like a traditional get() accesses a private data member maintaining the original purpose.

public:
A *getBase() { return static_cast<A *>(this); }

And then accessed like this:

f(b.getBase());

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).

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



Leave a reply



Submit