Connecting Tech Pros Worldwide Help | Site Map

Private inheritance question

 
LinkBack Thread Tools Search this Thread
  #1  
Old October 10th, 2005, 10:25 PM
Jonathan Potter
Guest
 
Posts: n/a
Default Private inheritance question

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, 10:35 PM
Alf P. Steinbach
Guest
 
Posts: n/a
Default 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, 10:45 PM
Victor Bazarov
Guest
 
Posts: n/a
Default 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 10th, 2005, 11:45 PM
Jonathan Potter
Guest
 
Posts: n/a
Default 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, 01:15 AM
Greg
Guest
 
Posts: n/a
Default 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, 02:05 PM
Victor Bazarov
Guest
 
Posts: n/a
Default 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, 02:05 PM
Greg
Guest
 
Posts: n/a
Default 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

 

Bookmarks

Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On

Popular Articles

What is Bytes?

We are a network of experts and professionals in IT and software development that help one another with answers to tough questions and share insights. Get the best answers to your questions from over 220,840 network members.