Connecting Tech Pros Worldwide Help | Site Map

Private inheritance question

  #1  
Old October 10th, 2005, 11:25 PM
Jonathan Potter
Guest
 
Posts: n/a
Hi, I was wondering if someone could explain something to me.
We recently upgraded to a new C++ compiler and found some old code wouldn't
compile.

Boiled down, the code that causes the error is:

class A
{
};

class B : private A
{
};

class C : public B
{
public:
// error here
void Func(A& a);
}


The error from the compiler is "'A' not accessible because 'B' uses
'private' to inherit from 'A'"

When I contacted the vendor's support about this I got the response:

"This is the way C++ works. The use of private inheritance turns all
non-private members of the base class into private members of the derived
class, and disallows all standard conversions between derived to base . This
construction

void Func(::A& a);

will work"

And he's right, it does work. I'm just wondering - what is the error in my
original construct? I can't see where the "conversion" that the response
refers to is. I'm not trying to convert anything from derived to base. I
simply have a function in the derived class to which I am passing a
parameter of the same type as the base class.

Thanks,
Jon


  #2  
Old October 10th, 2005, 11:35 PM
Alf P. Steinbach
Guest
 
Posts: n/a

re: Private inheritance question


* Jonathan Potter:[color=blue]
> Hi, I was wondering if someone could explain something to me.
> We recently upgraded to a new C++ compiler and found some old code wouldn't
> compile.
>
> Boiled down, the code that causes the error is:
>
> class A
> {
> };
>
> class B : private A
> {
> };
>
> class C : public B
> {
> public:
> // error here
> void Func(A& a);
> }
>
>
> The error from the compiler is "'A' not accessible because 'B' uses
> 'private' to inherit from 'A'"
>
> When I contacted the vendor's support about this I got the response:
>
> "This is the way C++ works. The use of private inheritance turns all
> non-private members of the base class into private members of the derived
> class, and disallows all standard conversions between derived to base . This
> construction
>
> void Func(::A& a);
>
> will work"
>
> And he's right, it does work. I'm just wondering - what is the error in my
> original construct? I can't see where the "conversion" that the response
> refers to is.[/color]

You've focused on the wrong part of the answer -- that's just supplementary
information. The important part is that A is a private member of B. In C you
were trying to access that private member because lookup of the unqualified A
finds members first.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
  #3  
Old October 10th, 2005, 11:45 PM
Victor Bazarov
Guest
 
Posts: n/a

re: Private inheritance question


Jonathan Potter wrote:[color=blue]
> Hi, I was wondering if someone could explain something to me.
> We recently upgraded to a new C++ compiler and found some old code wouldn't
> compile.
>
> Boiled down, the code that causes the error is:
>
> class A
> {
> };
>
> class B : private A
> {
> };
>
> class C : public B
> {
> public:
> // error here
> void Func(A& a);[/color]

'A' is inaccessible (private) base of 'B'. The name is visible, the
access is prohibited.
[color=blue]
> }[/color]
;
[color=blue]
>
>
> The error from the compiler is "'A' not accessible because 'B' uses
> 'private' to inherit from 'A'"
>
> When I contacted the vendor's support about this I got the response:
>
> "This is the way C++ works. The use of private inheritance turns all
> non-private members of the base class into private members of the derived
> class, and disallows all standard conversions between derived to base . This
> construction
>
> void Func(::A& a);
>
> will work"
>
> And he's right, it does work. I'm just wondering - what is the error in my
> original construct?[/color]

'A' _inside_ 'C' refers to 'B::A', which is private.
[color=blue]
> I can't see where the "conversion" that the response
> refers to is. I'm not trying to convert anything from derived to base. I
> simply have a function in the derived class to which I am passing a
> parameter of the same type as the base class.[/color]

Name lookup for an unqualified name 'A' finds '::C::B::A' and prefers it
over '::A'.

V
  #4  
Old October 11th, 2005, 12:45 AM
Jonathan Potter
Guest
 
Posts: n/a

re: Private inheritance question


Ah! Thank you both. That makes perfect sense!

So actually the fact that this code used to compile in the old compiler
(Visual C++ 6.0) was presumably an error in the first place?

"Victor Bazarov" <v.Abazarov@comAcast.net> wrote in message
news:EYB2f.40045$Tf5.25880@newsread1.mlpsca01.us.t o.verio.net...[color=blue]
>
> Name lookup for an unqualified name 'A' finds '::C::B::A' and prefers it
> over '::A'.[/color]

"Alf P. Steinbach" <alfps@start.no> wrote in message
news:434ae95b.44694765@news.individual.net...[color=blue]
>
> You've focused on the wrong part of the answer -- that's just
> supplementary
> information. The important part is that A is a private member of B. In C
> you
> were trying to access that private member because lookup of the
> unqualified A
> finds members first.[/color]


  #5  
Old October 11th, 2005, 02:15 AM
Greg
Guest
 
Posts: n/a

re: Private inheritance question


Victor Bazarov wrote:[color=blue]
> Jonathan Potter wrote:[color=green]
> > Hi, I was wondering if someone could explain something to me.
> > We recently upgraded to a new C++ compiler and found some old code wouldn't
> > compile.
> >
> > Boiled down, the code that causes the error is:
> >
> > class A
> > {
> > };
> >
> > class B : private A
> > {
> > };
> >
> > class C : public B
> > {
> > public:
> > // error here
> > void Func(A& a);[/color]
>
> 'A' is inaccessible (private) base of 'B'. The name is visible, the
> access is prohibited.
>[color=green]
> > }[/color]
> ;
>[color=green]
> >
> >
> > The error from the compiler is "'A' not accessible because 'B' uses
> > 'private' to inherit from 'A'"
> >
> > When I contacted the vendor's support about this I got the response:
> >
> > "This is the way C++ works. The use of private inheritance turns all
> > non-private members of the base class into private members of the derived
> > class, and disallows all standard conversions between derived to base . This
> > construction
> >
> > void Func(::A& a);
> >
> > will work"
> >
> > And he's right, it does work. I'm just wondering - what is the error in my
> > original construct?[/color]
>
> 'A' _inside_ 'C' refers to 'B::A', which is private.
>[color=green]
> > I can't see where the "conversion" that the response
> > refers to is. I'm not trying to convert anything from derived to base. I
> > simply have a function in the derived class to which I am passing a
> > parameter of the same type as the base class.[/color]
>
> Name lookup for an unqualified name 'A' finds '::C::B::A' and prefers it
> over '::A'.[/color]

I would characterize the behavior slightly differently: the compiler
prefers "::C::B::A" because it finds it first. Once the C++ compiler
finds a declaration to match a name, it stops looking for any other
matching declarations, including declarations for the same symbol that
may offer a different level of access.

So whatever the access restriction is on the first declaration found,
is the access level that the compiler will apply to the name when it
appears in the source code. In this case the global namespace specifier
ensures that the compiler will find ::A first because it ensures that
the compiler will be looking only in the global namespace for A.

Greg

  #6  
Old October 11th, 2005, 03:05 PM
Victor Bazarov
Guest
 
Posts: n/a

re: Private inheritance question


Greg wrote:[color=blue]
> [...]
> I would characterize the behavior slightly differently: the compiler
> prefers "::C::B::A" because it finds it first.[/color]

Yes and no. The compiler finds all of them. However, if a member with
that name exists, the other names are discarded (not considered). If
they were equally considered, there would be ambiguity (before checking
access specifiers). Of course, we could say that it finds the member
first (and stops looking for others) if we can prove (or assume) that the
compiler looks for members first.
[color=blue]
> Once the C++ compiler
> finds a declaration to match a name, it stops looking for any other
> matching declarations, including declarations for the same symbol that
> may offer a different level of access.
>
> So whatever the access restriction is on the first declaration found,
> is the access level that the compiler will apply to the name when it
> appears in the source code. In this case the global namespace specifier
> ensures that the compiler will find ::A first because it ensures that
> the compiler will be looking only in the global namespace for A.[/color]

V
  #7  
Old October 12th, 2005, 03:05 PM
Greg
Guest
 
Posts: n/a

re: Private inheritance question


Victor Bazarov wrote:[color=blue]
> Greg wrote:[color=green]
> > [...]
> > I would characterize the behavior slightly differently: the compiler
> > prefers "::C::B::A" because it finds it first.[/color]
>
> Yes and no. The compiler finds all of them. However, if a member with
> that name exists, the other names are discarded (not considered). If
> they were equally considered, there would be ambiguity (before checking
> access specifiers). Of course, we could say that it finds the member
> first (and stops looking for others) if we can prove (or assume) that the
> compiler looks for members first.[/color]

Only when searching for a function declaration is the compiler's search
exhaustive. For other types of names, including those in this example,
the compiler follows this rule:

"In all cases listed in 3.4.1, the scopes are searched for a
declaration in the order listed in each of the respective categories;
name lookup ends a soon as a declaration is found for the name. If no
declaration is found, the program is ill-formed." §3.4.1/1

I should clarify that the compiler when searching a particular scope
always searches that scope completely. In this way, names duplicated in
different declarations within the same scope prompt an error - while
names declared in one scope tend to "hide" duplicate names declared in
more distant scopes.

Greg

Closed Thread


Similar Threads
Thread Thread Starter Forum Replies Last Post
how to use private inheritance zhangyefei.yefei@gmail.com answers 4 August 25th, 2008 02:45 AM
Private inheritance question KD answers 2 June 27th, 2008 05:43 PM
C++ quiz question: private inheritance __PPS__ answers 8 October 21st, 2005 11:55 AM
Base class pointers and private inheritance Dave Theese answers 4 July 19th, 2005 05:37 PM