There are tons of questions regarding this error and all of the answers seem to imply that downcasting is impossible. Only this answer mentions friendship as possible solution, at least as I understand it. However the following code (irrelevant stuff removed for clarity) does not compile:
class C;
class A {
friend class C; // this does not help
};
class B : protected A {
friend class C; // this does not help either
};
class C {
public:
void foo(A* a) {};
};
B b;
C c;
void bar()
{
c.foo(&b); // this produces error: class A is an inaccessible base of B
}
Why friendship does not work on a reference? After all, "C" is perfectly capable of calling protected methods of "A" through pointer to "B".
The full error is
prog.cc: In function 'void bar()':
prog.cc:20:13: error: 'A' is an inaccessible base of 'B'
20 | c.foo(&b);
As we know a private member is inaccessible (not just private) in derived classes while public and protected are directly accessible there. If a class declares another class as a friend then the latter has full-access to the members of the first.
Inheritance and friendship in C++ In C++, the friendship is not inherited. It means that, if one parent class has some friend functions, then the child class will not get them as friend.
Constructor cannot be inherited but a derived class can call the constructor of the base class.
Inheritance enables you to create new classes that reuse, extend, and modify the behavior defined in other classes. The class whose members are inherited is called the base class, and the class that inherits those members is called the derived class. A derived class can have only one direct base class.
Your code is equivalent to this:
B b;
C c;
A * a = &b; // <- This cast produces the error
c.foo(a);
You cannot cast &b
as A*
since the base class is protected, regardless of the friendship of C
.
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).
In the global scope B is not visible as A, because of protected inheritance.
Only class B itself, classes inherited from B and class C (because the friendship relation) "know" that B is inheriting A. But the rest of the world (including global scope) doesnt'.
So to achieve what you want, you could call
c.foo(&b)
within C scope, for example using some wrapper function, something like (although bad design decision):
#include <iostream>
#include <cstdlib>
class C;
class A {
friend class C; // this does not help
};
class B : protected A {
friend class C; // this does not help either
};
class C {
public:
void foo() {
B b;
foo(&b); // this call is OK within C-scope
}
private:
void foo(A* /*a*/) {
std::cout << "C::foo(A* a)\n";
};
};
int main()
{
std::cout << "Hello, Wandbox!" << std::endl;
B b;
C c;
//c.foo(&b); // this produces error: class A is an inaccessible base of B
c.foo(); // this is calling c.foo(A*) internally
}
or live:
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