Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c++

Why is the call to f not resolving to the first function overload? I get the error:

source.cpp: In function 'int main()':
source.cpp:12:31: error: 'A' is an inaccessible base of 'B'

class A {}; class B : A {};

void f(const A &)  { std::cout << "const A &"; }
template <typename T> void f(T) { std::cout << "Generic";  }

int main() {

   B b;

   f(dynamic_cast<const A &>(b));

}

Note that if I take out the dynamic_cast the code will work yet the second f is called (it prints "Generic"). But what I'm trying to do is to get the first call. I figured a dynamic_cast would work, but for some reason it causes problems. What am I doing wrong here?

like image 741
template boy Avatar asked Dec 13 '12 22:12

template boy


2 Answers

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());
like image 191
imreal Avatar answered Nov 15 '22 07:11

imreal


A is a private base of B, so there are very few places where an object of type B can be treated as an A&. If you change the inheritance to public the cast will work, and select the non-template version of f. But dynamic_cast is overkill; every object of type B is an object of type A, so you can use static_cast to disambiguate the call.

like image 21
Pete Becker Avatar answered Nov 15 '22 05:11

Pete Becker