11

The following simple example will produce a compiler error, since I accidently use private inheritance:

main.cpp:21: error: ‘A’ is an inaccessible base of ‘B’

class A
{


};

class B : /*ups forgot that -> public*/ A
{


};

int main(int , char *[])
{
    A* test = new B;

    return 0;
}

Could you help me and explain what exactly is inaccessible in the base class and why it is needed in the conversion from B* to A*?

Ronald McBean
  • 1,417
  • 2
  • 14
  • 27
  • 1
    [What are access specifiers? Should I inherit with private, protected or public?](http://stackoverflow.com/questions/5447498/what-are-access-specifiers-should-i-inherit-with-private-protected-or-public/%5d) is a good read for you. – Alok Save Sep 05 '11 at 12:07
  • 1
    also this link maybe useful http://www.gotw.ca/publications/mill06.htm – Alessandro Teruzzi Sep 05 '11 at 12:40

6 Answers6

12

Private inheritance means that for everyone except B (and B's friends), B is not derived from A.

Jan
  • 1,807
  • 13
  • 26
  • Could you explain that in terms of `constructors` on function level? What functions are inaccessible due to the private inheritance? – Ronald McBean Sep 05 '11 at 11:47
  • @Ronald: The entire class is inaccessible, including all constructors, and any other members. Nothing is accessible. – Mike Seymour Sep 05 '11 at 11:51
  • But why can I create a `class B` then at all if `class A` is totally inaccessible? Sorry I am confused :-) – Ronald McBean Sep 05 '11 at 11:53
  • 2
    @Ronald McBean: Because `A::A()` is called (implicitly) from `B::B()`, and all B's members _can_ access A. – MSalters Sep 05 '11 at 11:55
  • Because when you construct B, B's constructor calls A's constructor, which is fine. B can access all public members of A, including the (compiler generated in this case) constructor. – Jan Sep 05 '11 at 11:56
  • 1
    @Ronald: The private base class is accessible by all of `B`'s members and friends, including the constructors, so there's no problem with instantiating `B`. It is not accessible anywhere else, which is why the pointer conversion fails. – Mike Seymour Sep 05 '11 at 11:57
  • 1
    @Ronald, you were confused by wrong answers that were removed. @Jan's answer is correct: "external" code doesn't know B inherits from A, so you can't use an `A*` to point on a `B*`. The construction is not the problem. – Eran Sep 05 '11 at 11:57
  • It's actually quite like private members and functions: B can access them, others can not. – Jan Sep 05 '11 at 12:25
  • Thank you all, your answer and all comments helped a lot! – Ronald McBean Sep 05 '11 at 13:00
  • But a static (or C style) cast is apparently possible? – NetMage Jun 03 '21 at 18:23
8

Could you help me and explain what exactly is inaccessible in the base class and why it is needed in the conversion from B* to A*?

Ouside of B and the friends of B, the simple fact that B is an A is not visible. This is not hiding a member variable or member function, but hiding the relationship itself. That is why from main you cannot bind the result of new B with a pointer to A, because as far as main is concerned, B is not an A (in the same way that you could not do A * p = new unrelated;)

As to why it is needed, the answer it exactly the same: because without access to the relationship, the compiler does not know (well, it knows, but will not tell you) how to obtain a pointer to the A subject inside B, because as far as it can see within that context there is no relationship between A and B at all.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
3

The conversion from B* to A* is inaccessible, because the base-class subobject is private. When you convert B* to A*, you return the pointer to the base-class subobject. The latter must be accessible for the conversion to be accessible. In any function that is friend to B the conversion becomes accessible. By the way, you can always access the conversion by an explicit cast.

A* p = (A*)(new B);

Note that in some cases just accessible conversion is required, but in some cases it is required that A be a public (stronger than accessible) base of B. For example, when you try to catch an exception of type B with catch(A&) - it is required that A be a public base class of B.

Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
  • 1
    The explicit cast you mentioned, is it functionally the same as a `reinterpret_cast`? Meaning, from a compiler point of view, you convert two totally unrelated types? – Ronald McBean Sep 05 '11 at 12:45
  • 1
    @Ronald: To be perfectly hones, I am not sure. In the standard, the examples use C-style cast without mentioning which cast it is. You can try by writing static_cast. If it works, then it is static_cast, otherwise it's reinterpret_cast – Armen Tsirunyan Sep 05 '11 at 12:47
1

Since the reference or pointer of Base class can not point to object of inherited class, does it mean that protected and private inheritance is nothing to do with polymorphism?

Donglei
  • 275
  • 1
  • 10
0

Public/private inheritance is equivalent to public/private member variable.

The result of the conversion is a reference to the base class subobject of the derived class object.

I think the accessibility means the accessibility of the base class subobject of the derived class object.For client,only if we ues public inheritance,the base class subobject is accessible.For the member function of derived class,no matter we use public/protected/privaye inheritance, the base class subobject is accessible.

class A{

};

class B: private  A{
private:
    int* m_pb;
public:
    B(){m_pb=new int(10)};
    void func()
    {
        A* pa= new B;      //OK
        int *pmb = m_pb;   //OK 
    }

};
int main()
{
    B* pb = new B;
    A* pa= pb;             // inaccessible
    int *pmb = pb->m_pb;   // inaccessible 
}

OK.I means that public/private inheritance is equivalent to public/private member variable.

reference: http://pic.dhe.ibm.com/infocenter/ratdevz/v8r5/index.jsp?topic=%2Fcom.ibm.tpf.toolkit.compilers.doc%2Fref%2Flangref_os390%2Fcbclr21011.htm

jie.zhou
  • 1
  • 1
0

Since B is inherited from A, the default constructor of A would be called before the constructor of B. But because it is private and not inherited to B, you get a compiler error.

B Faley
  • 17,120
  • 43
  • 133
  • 223