3

I'm getting "error: ‘A’ is an inaccessible base of ‘B’" in static_cast of the following example:

template<typename Derived>
class A {
protected:
    void funA() { static_cast<Derived *> (this)->funB(); }
};

class B: protected A<B> {
public:
    void funB() {}
    void funC() { funA(); }
};

int main() {
    B().funC();
    return 0;
}

But it compiles/works well when using reinterpret_cast or C-style type cast ((Derived *)this)->funB() instead. Is this behavior correct?

Compiler used: gcc version 4.5.1 20100924 (Red Hat 4.5.1-4) (GCC).

Thanks.

user1072688
  • 61
  • 1
  • 4
  • 4
    A C-style cast just allows the compiler to pick the cast that it thinks is most appropriate. There is no way to tell whether it picked the wrong cast, except when your code crashes! – Neil Dec 17 '11 at 23:35
  • @Neil The C-style cast does the "right" thing here, except the code should be fixed. – curiousguy Dec 19 '11 at 05:59
  • @curiousguy But if B inherited from more than one class, then it would still do a `reinterpret_cast<>`, which might be wrong. – Neil Dec 19 '11 at 22:20
  • @Neil Wrong, this cast doesn't do a `reinterpret_cast<>` in the proposed code. Once again: **this cast does the right.** – curiousguy Dec 20 '11 at 00:04
  • @curiousguy Fair enough, I'll upvote your answer. – Neil Dec 20 '11 at 22:50

3 Answers3

2

I'm getting "error: ‘A’ is an inaccessible base of ‘B’" in static_cast of the following example:

This is expected: B is derived from A<B>, but this inheritance is protected: only B and its derived classes can use the fact B is derived from A<B>.

But it compiles/works well when using reinterpret_cast (...) instead. Is this behavior correct?

This is expected: reinterpret_cast does not care about inheritance or other relations between types.

If possible, reinterpret_cast just gives you a pointer with the same value (pointing to the same byte) as the original pointer value.

This is merely hiding the problem.

But it compiles/works well when using (...) C-style type cast ((Derived *)this)->funB() instead. Is this behavior correct?

This is expected: C-style casts ignore access control. This is merely hiding the problem.

The fix is to make the inheritance relation between A<B> and B accessible where you want to use it.

curiousguy
  • 8,038
  • 2
  • 40
  • 58
1

Yes, that seems right. You've got protected inheritance, and A<B> is not derived from or a friend of B, so it cannot see B's base class to tell that the static_cast is valid.

  • I didn't mention friend because you cannot friend a template type parameter, but of course you're right, the friendship would be the other way around, so there would be no problem with that. Thanks, updated. –  Dec 17 '11 at 23:38
  • Thank you all, I've got the point. Still I doubt I read about this before. How to correctly workaround this? – user1072688 Dec 17 '11 at 23:43
  • That depends. Should every class know that `B` inherits from `A`? If so, make the inheritance public. If not, as Neil said, make `A` a friend of `B`. –  Dec 17 '11 at 23:47
  • So I see for this pattern 'protected' should not be uses - to allow static_cast make a type-checks. To isolate internals, one more class could be derived from B using protect. – user1072688 Dec 17 '11 at 23:51
1

Protected and private inheritance do not create an is a relationship between classes, which is required in order to do static_cast outside a class or its friend. Essentially, private/protected inheritance is an inheritance of an implementation, not an inheritance of an interface. That is why static_cast does not work.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • "_Protected and private inheritance do not create an *is a* relationship between classes_" they do, but with protected or private access, obviously. – curiousguy Dec 19 '11 at 05:55
  • 1
    @curiousguy Please do your "due diligence" before commenting, and especially downvoting: [private inheritance is a syntactic variant of composition](http://www.parashift.com/c++-faq-lite/private-inheritance.html#faq-24.2), not an *is-a*, but rather a *has-a* relationship. – Sergey Kalinichenko Dec 19 '11 at 10:11
  • "Private inheritance" is inheritance that is private, nothing less, nothing more. Obviously it is not a syntaxic variant of composition. Where does this nonsense come from? – curiousguy Dec 19 '11 at 10:45
  • 1
    @curiousguy "Private inheritance" is an oxymoron, nothing less, nothing more. Do not let it's syntactic similarity to *inheritance* in C++ throw you off. Please follow the link to C++ FAQ from my previous message, or read a particularly well-articulated item #34 of ["Effective C++"](http://books.google.com/books?id=umgPAQAAMAAJ&dq=isbn:0201924889) by Scott Meyers. Checking out other [FAQs](http://www.cplusplus.com/forum/beginner/12899/), [tutotials](http://www.cprogramming.com/tutorial/private.html), and [articles](http://www.gotw.ca/publications/mill06.htm) may help too. – Sergey Kalinichenko Dec 19 '11 at 12:40
  • @curiousguy Searching SO for "private inheritance" may also get you some [very](http://stackoverflow.com/questions/1576978/private-inheritance) [good](http://stackoverflow.com/questions/5372070/protected-private-inheritance-casting) [answers](http://stackoverflow.com/questions/6297331/when-to-use-c-private-inheritance-over-composition). – Sergey Kalinichenko Dec 19 '11 at 12:44
  • OK, you got tons of links. Doesn't impress much, or at all. Do you **one** link that proves that private inheritance is not a private IS-A relationship? – curiousguy Dec 19 '11 at 14:25
  • @curiousguy There is no such proof, because *private is-a relationship* is not a meaningful concept that gained a wide recognition (or any recognition, for that matter). Run a search for "private is-a relationship" and check the number of hits you get to see what I mean. – Sergey Kalinichenko Dec 19 '11 at 14:41
  • It may not have gained any recognition, but it is not wrong. Saying that inheritance is composition is wrong. – curiousguy Dec 19 '11 at 15:00
  • @curiousguy *Private is-a relationship* is *not wrong* only to the extent that *meaningless* statements cannot be judged right or wrong. Saying that "inheritance *is* composition" would definitely be wrong, but then I did not say that. Instead, I said that C++ construct of **private inheritance** *expresses* a form of composition (or in the words of Scott Meyers, *is implemented in terms of* relationship). And that is a correct statement, as inheriting privately exhibits all visible properties of a containment, and no visible properties of an inheritance. – Sergey Kalinichenko Dec 19 '11 at 15:32
  • Private inheritance "exhibits" the "visible property" that members of the (private) base class are "inherited" by the derived class, notably virtual functions. – curiousguy Dec 19 '11 at 15:38
  • @curiousguy That member functions of the inheriting class can call or even override virtual functions of a privately inherited class is not a *visible* property: rather, it is an implementation detail, conveniently hidden from your callers. You can re-implement all of your privately inherited functionality using containment. Doing certain things, such as overriding virtual functions, would require a little more work, but in the end it is certainly doable: the users of your class would recompile without noticing a change. Naturally, you cannot pull the same trick with public inheritance. – Sergey Kalinichenko Dec 19 '11 at 15:58
  • And that further derived classes can again override these virtual functions declared in private base classes is also a detail? – curiousguy Dec 19 '11 at 16:15
  • @curiousguy It's much worse: it is a mistake in the language design :):):) Bjarne Stroustrup has been asked about it in an interview back in 1996 ([here is the link](http://www.eptacom.net/pubblicazioni/pub_eng/stroustr.html); scroll down to the first coding example to see his answer). He could not come up with a convincing defense for the feature, admitting that public overriding of privately inherited functions is "a messy example", and noting in the end that he did not outlaw the feature because he is "against restrictions for which [he does not] see a practical purpose." – Sergey Kalinichenko Dec 19 '11 at 16:43