Why would the conversion between derived* to base* fails with private inheritance?
Asked Answered
N

7

20

Here is my code -

#include<iostream>
using namespace std;

class base
{
public:
    void sid()
    {
    }  
};

class derived : private base
{
public:
    void sid()
    {
    }
};

int main()
{
    base * ptr;
    ptr = new derived; // error: 'base' is an inaccessible base of 'derived'
    ptr->sid();
    return 0;
}

This gives a compile time error.

error: 'base' is an inaccessible base of 'derived'

Since the compiler will try and call the base class sid() why do I get this error? Can someone please explain this.

Nimiety answered 9/9, 2010 at 8:19 Comment(6)
You did not declare the method virtual. Which error is it you are getting exactly?Gastrolith
At its current form this has nothing to do with function sid(). You are using private inheritance hence the conversion from derived* to base* is failing. Is that what you are asking or is it something to do with method sid()?Hydrocele
possible duplicate of Protected derived classJenijenica
why are you using private inheritance instead of public ?Valentinvalentina
@Naveen: Yes that is exactly what I am asking? Why does it fail?Nimiety
What's the point of the empty private: access specifier? Why leak memory in a simple program? Either delete it or use auto_ptr.Mope
H
16

$11.2/4 states-

A base class B of N is accessible at R, if

  • an invented public member of B would be a public member of N, or
  • R occurs in a member or friend of class N, and an invented public member of B would be a private or protected member of N, or
  • R occurs in a member or friend of a class P derived from N, and an invented public member of B would be a private or protected member of P, or
  • there exists a class S such that B is a base class of S accessible at R and S is a base class of N accessible at R."

Here 'B' is 'Base', 'N' is 'Derived' and 'R' is main.

  1. Consider the 2nd bullet- 'R occurs in a member or friend of a class N,...'. This clause does not apply as 'R'(main) is neither a member nor friend of 'N'(Derived)

  2. Consider the 3rd bullet- 'R occurs in a member or friend of a class P....'. This claus also does not apply for the same reasons as above

  3. Consider the 4th bullet- Once again this clause does not apply

Thus we can conclude that 'Base' is not an accessible class of 'Derived'.

$11.2/5 states -

If a base class is accessible, one can implicitly convert a pointer to a derived class to a pointer to that base class (4.10, 4.11). [ Note: it follows that members and friends of a class X can implicitly convert an X* to a pointer to a private or protected immediate base class of X. —end note ]

Since Base is not an accessible class of Derived when accessed in main, the Standard conversion from Derived class to Base class is ill-formed. Hence the error.

EDIT 2:

Study the error messages of some popular compilers and that should help you get a better understanding. Note how the word 'inaccessible' pops up so frequently and consistently across all the error messages

The references are from the draft standard N3000. I am yet to download the latest draft :)

GCC prog.cpp: In function ‘int main()’: prog.cpp:27: error: ‘base’ is an inaccessible base of ‘derived’

Comeau Online "ComeauTest.c", line 26: error: conversion to inaccessible base class "base" is not allowed ptr = new derived;

VS2010 error C2243: 'type cast' : conversion from 'derived *' to 'base *' exists, but is inaccessible

Hippocrates answered 9/9, 2010 at 8:28 Comment(3)
Can you kindly provide your reference.Nimiety
@Bruce: Oh sorry, I forgot to mention that the references are from the draft standard N3000. I found that C++03 has some confusing statements to understand this concept. I will update my post accordinglyHippocrates
See Douglas Leeder's and ereOn's answers for human readable and quick solutions.Ovariotomy
E
35

I suspect the problem is that you can't convert a derived pointer to a base pointer, as the inheritance is private.

Excitor answered 9/9, 2010 at 8:25 Comment(3)
Why cant I do this? What are the implementation problems in this?Nimiety
Private inheritance means that you don't want the base class interface to be accessible other code than the child class code.Mukund
Didn't really feel like spending time interpreting Chubsdad's answer and this was exactly what I needed to know. Was missing a public statement on my derived class definitionMarylynnmarylynne
H
16

$11.2/4 states-

A base class B of N is accessible at R, if

  • an invented public member of B would be a public member of N, or
  • R occurs in a member or friend of class N, and an invented public member of B would be a private or protected member of N, or
  • R occurs in a member or friend of a class P derived from N, and an invented public member of B would be a private or protected member of P, or
  • there exists a class S such that B is a base class of S accessible at R and S is a base class of N accessible at R."

Here 'B' is 'Base', 'N' is 'Derived' and 'R' is main.

  1. Consider the 2nd bullet- 'R occurs in a member or friend of a class N,...'. This clause does not apply as 'R'(main) is neither a member nor friend of 'N'(Derived)

  2. Consider the 3rd bullet- 'R occurs in a member or friend of a class P....'. This claus also does not apply for the same reasons as above

  3. Consider the 4th bullet- Once again this clause does not apply

Thus we can conclude that 'Base' is not an accessible class of 'Derived'.

$11.2/5 states -

If a base class is accessible, one can implicitly convert a pointer to a derived class to a pointer to that base class (4.10, 4.11). [ Note: it follows that members and friends of a class X can implicitly convert an X* to a pointer to a private or protected immediate base class of X. —end note ]

Since Base is not an accessible class of Derived when accessed in main, the Standard conversion from Derived class to Base class is ill-formed. Hence the error.

EDIT 2:

Study the error messages of some popular compilers and that should help you get a better understanding. Note how the word 'inaccessible' pops up so frequently and consistently across all the error messages

The references are from the draft standard N3000. I am yet to download the latest draft :)

GCC prog.cpp: In function ‘int main()’: prog.cpp:27: error: ‘base’ is an inaccessible base of ‘derived’

Comeau Online "ComeauTest.c", line 26: error: conversion to inaccessible base class "base" is not allowed ptr = new derived;

VS2010 error C2243: 'type cast' : conversion from 'derived *' to 'base *' exists, but is inaccessible

Hippocrates answered 9/9, 2010 at 8:28 Comment(3)
Can you kindly provide your reference.Nimiety
@Bruce: Oh sorry, I forgot to mention that the references are from the draft standard N3000. I found that C++03 has some confusing statements to understand this concept. I will update my post accordinglyHippocrates
See Douglas Leeder's and ereOn's answers for human readable and quick solutions.Ovariotomy
M
8

Chusbad provided an in-depth explanation involving the standard, I'll try to provide an accessible explanation.

In C++, there are 3 access level specifiers: public, protected and private. Those are meant to determine WHO can access methods, attributes or base classes. It is typical amongst Object Oriented languages.

Here, you elected private inheritance. Conceptually this means that you seek to HIDE the fact that Derived inherits from Base to outsiders, which generally means this is an implementation details.

As a consequence, the "exterior" is unaware of this relationship. This is enforced by the compiler with this inaccessible message.

From a design point of view, private inheritance is not generally required. Either the Liskov Substitution Principle applies and you use public inheritance, either it's an implementation detail and you use composition.

Mouthpiece answered 9/9, 2010 at 9:29 Comment(0)
L
6

You know that class derived inherits from class base, but the main() function doesn't know it. The reason the main() function doesn't know it is that you made class derived inherit PRIVATELY from class base.

Therefore when you try to assign new derived to ptr, the pointer types are not compatible.

Lashanda answered 9/9, 2010 at 8:27 Comment(1)
@WP: Can you please elaborate on your answerNimiety
A
5

Try this:

#include<iostream>
#include<conio.h>
using namespace std;

class base
{
      private:
      public:
          virtual void sid() // You might want to declare sid virtual
             {
                  cout<<"base";
             } 
          virtual ~base() // You then probably need a virtual destructor as well.
             {
             } 
};

class derived : public base //public inheritance
{
      private:
      public:
             void sid()
             {
                  cout<<"derived";
             }
};

int main()
{
    base * ptr;
    ptr = new derived;
    ptr->sid();
    getch();
    return 0;
}
Aryn answered 9/9, 2010 at 8:26 Comment(3)
You meant virtual void sid()? Also you need the base class destructor to be virtual.Hydrocele
@Naveen: Thanks. I was on my way to add the destructor ;) Also yes, the private was a typo.Aryn
The virtual destructor is a good idea. Putting virtual on the sid function is contrary to a stated goal of the original poster.Lashanda
A
1

this gives error C2243: 'type cast' : conversion from 'derived *' to 'base *' exists, but is inaccessible This derived class has been inherited privately .so base class object is not gets created when derieved get creation happens. to create the derive object first calls goes to create the base class object that not happening. soltuion is to derive the class publicly. it doesnit matter whether your using virtual keyword with member functions or not.

Ashbaugh answered 9/9, 2010 at 9:44 Comment(0)
C
0

You need to declare your sid() function in the base class as virtual. A virtual function can be replaced by a derived class. Otherwise, you would likely get a compiler error.

Chicky answered 9/9, 2010 at 8:26 Comment(2)
You know, I HATE it when people downvote, and don't leave a comment.Chicky
I didn't down-vote this answer, but I think it's mistaken. I've seen compilers give warnings for hiding a base-class function with a derived-class one, but never an error.Beefcake

© 2022 - 2024 — McMap. All rights reserved.